Credits
This commit is contained in:
parent
3620df450e
commit
02e7cac3a9
81
data/config/credits.json
Normal file
81
data/config/credits.json
Normal file
@ -0,0 +1,81 @@
|
||||
{
|
||||
"developers": [
|
||||
{
|
||||
"id": 0,
|
||||
"dev": "Welcome App's coding:\nCosmo & GlouriousEggroll"
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"dev": "Welcome App's UI:\nPizzaLovingNerd - risiOS BDFL"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"dev": "Webapps manager:\nThe Linux Mint team"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"dev": "Standalone gamescope session:\nThe ChimeraOS Team & KyleGospo"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"dev": "Repositories, and firmware Manager, \nand The tiling in gnome-shell with pop-shell: \nThe Pop!OS Team"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"dev": "Hybrid GPU Controls:\nasus-linux"
|
||||
}, {
|
||||
"id": 6,
|
||||
"dev": "ISO testing VMs:\nAkiToasterUwU"
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"dev": "APX package manager:\nThe Vanilla OS Team"
|
||||
}, {
|
||||
"id": 8,
|
||||
"dev": "Wallpapers:\nNeytirix & Colorman"
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"dev": "Logo artist:\nnesper8 (willsmanic) & MattsCreative & Piaf_Jaune"
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"dev": "Kernel Base:\nCachyOS team (ptr1337)"
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"dev": "Themeing:\nVinceliuice & Papirus"
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"dev": "Encryption Support:\nSkimmingDeath"
|
||||
},
|
||||
{
|
||||
"id": 13,
|
||||
"dev": "Graphics Drivers:\nKisak & Oibaf"
|
||||
},
|
||||
{
|
||||
"id": 14,
|
||||
"dev": "pikman package manager, Package Builder Hardware, \nServer Hosting:\nFerreo"
|
||||
}, {
|
||||
"id": 15,
|
||||
"dev": "Website:\nFerreo & BL4Z3"
|
||||
},
|
||||
{
|
||||
"id": 16,
|
||||
"dev": "Anti Snap:\nThe Xtradeb team"
|
||||
},
|
||||
{
|
||||
"id": 17,
|
||||
"dev": "Technical Advisors:\nFerreo & ptr1337 & Zukureneno"
|
||||
},
|
||||
{
|
||||
"id": 18,
|
||||
"dev": "Audio Artist:\n4lk4"
|
||||
},
|
||||
{
|
||||
"id": 19,
|
||||
"dev": "Financial Contributors:\nnesper8 (willsmanic) & FlibbyJibbit & Zukureneno"
|
||||
}
|
||||
]
|
||||
}
|
157
src/welcome_content_page/community_page/mod.rs
Normal file
157
src/welcome_content_page/community_page/mod.rs
Normal file
@ -0,0 +1,157 @@
|
||||
// GTK crates
|
||||
use duct::cmd;
|
||||
use std::path::Path;
|
||||
use std::fs;
|
||||
use serde::Deserialize;
|
||||
use std::{thread, time};
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
use adw::prelude::*;
|
||||
use adw::*;
|
||||
use glib::*;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(PartialEq, Debug, Eq, Hash, Clone, Ord, PartialOrd, Deserialize)]
|
||||
struct setup_steps_entry {
|
||||
id: i32,
|
||||
title: String,
|
||||
subtitle: String,
|
||||
icon: String,
|
||||
button: String,
|
||||
command: String
|
||||
}
|
||||
|
||||
pub fn setup_steps_page(
|
||||
setup_steps_content_page_stack: >k::Stack,
|
||||
window: &adw::ApplicationWindow,
|
||||
internet_connected: &Rc<RefCell<bool>>
|
||||
) {
|
||||
let internet_connected_status = internet_connected.clone();
|
||||
|
||||
let (internet_loop_sender, internet_loop_receiver) = async_channel::unbounded();
|
||||
let internet_loop_sender = internet_loop_sender.clone();
|
||||
// The long running operation runs now in a separate thread
|
||||
gio::spawn_blocking(move || loop {
|
||||
thread::sleep(time::Duration::from_secs(1));
|
||||
internet_loop_sender
|
||||
.send_blocking(true)
|
||||
.expect("The channel needs to be open.");
|
||||
});
|
||||
|
||||
let setup_steps_page_box = gtk::Box::builder()
|
||||
.vexpand(true)
|
||||
.hexpand(true)
|
||||
.build();
|
||||
|
||||
let setup_steps_page_listbox = gtk::ListBox::builder()
|
||||
.margin_top(20)
|
||||
.margin_bottom(20)
|
||||
.margin_start(20)
|
||||
.margin_end(20)
|
||||
.vexpand(true)
|
||||
.hexpand(true)
|
||||
.build();
|
||||
setup_steps_page_listbox.add_css_class("boxed-list");
|
||||
|
||||
let setup_steps_page_scroll = gtk::ScrolledWindow::builder()
|
||||
// that puts items vertically
|
||||
.hexpand(true)
|
||||
.vexpand(true)
|
||||
.child(&setup_steps_page_box)
|
||||
.propagate_natural_width(true)
|
||||
.propagate_natural_height(true)
|
||||
.build();
|
||||
|
||||
let internet_loop_context = MainContext::default();
|
||||
// The main loop executes the asynchronous block
|
||||
internet_loop_context.spawn_local(
|
||||
clone!(@strong internet_connected_status, @weak setup_steps_page_box => async move {
|
||||
while let Ok(_state) = internet_loop_receiver.recv().await {
|
||||
if *internet_connected_status.borrow_mut() == true {
|
||||
setup_steps_page_box.set_sensitive(true);
|
||||
} else {
|
||||
setup_steps_page_box.set_sensitive(false);
|
||||
}
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
let mut json_array: Vec<setup_steps_entry> = Vec::new();
|
||||
let json_path = "/home/ward/builds/pkg-pika-welcome/data/config/setup_steps.json";
|
||||
let json_data = fs::read_to_string(json_path).expect("Unable to read json");
|
||||
let json_data: serde_json::Value = serde_json::from_str(&json_data).expect("JSON format invalid");
|
||||
if let serde_json::Value::Array(setup_steps) = &json_data["setup_steps"] {
|
||||
for setup_steps_entry in setup_steps {
|
||||
let setup_steps_entry_struct: setup_steps_entry = serde_json::from_value(setup_steps_entry.clone()).unwrap();
|
||||
json_array.push(setup_steps_entry_struct);
|
||||
}
|
||||
}
|
||||
|
||||
for setup_steps_entry in json_array {
|
||||
let (entry_command_status_loop_sender, entry_command_status_loop_receiver) = async_channel::unbounded();
|
||||
let entry_command_status_loop_sender: async_channel::Sender<bool> = entry_command_status_loop_sender.clone();
|
||||
|
||||
let entry_title = setup_steps_entry.title;
|
||||
let entry_subtitle = setup_steps_entry.subtitle;
|
||||
let entry_icon = setup_steps_entry.icon;
|
||||
let entry_button = setup_steps_entry.button;
|
||||
let entry_command = setup_steps_entry.command;
|
||||
let entry_row = adw::ActionRow::builder()
|
||||
.title(t!(&entry_title))
|
||||
.subtitle(t!(&entry_subtitle))
|
||||
.vexpand(true)
|
||||
.hexpand(true)
|
||||
.build();
|
||||
let entry_row_icon = gtk::Image::builder()
|
||||
.icon_name(entry_icon)
|
||||
.pixel_size(80)
|
||||
.vexpand(true)
|
||||
.valign(gtk::Align::Center)
|
||||
.build();
|
||||
let entry_row_button = gtk::Button::builder()
|
||||
.label(t!(&entry_button))
|
||||
.vexpand(true)
|
||||
.valign(gtk::Align::Center)
|
||||
.build();
|
||||
entry_row.add_prefix(&entry_row_icon);
|
||||
entry_row.add_suffix(&entry_row_button);
|
||||
|
||||
entry_row_button.connect_clicked(clone!(@strong entry_command, @weak window => move |_| {
|
||||
gio::spawn_blocking(clone!(@strong entry_command_status_loop_sender, @strong entry_command => move || {
|
||||
if Path::new("/tmp/pika-welcome-exec.sh").exists() {
|
||||
fs::remove_file("/tmp/pika-welcome-exec.sh").expect("Bad permissions on /tmp/pika-installer-gtk4-target-manual.txt");
|
||||
}
|
||||
fs::write("/tmp/pika-welcome-exec.sh", "#! /bin/bash\nset -e\n".to_owned() + &entry_command).expect("Unable to write file");
|
||||
let _ = cmd!("chmod", "+x", "/tmp/pika-welcome-exec.sh").read();
|
||||
let command = cmd!("/tmp/pika-welcome-exec.sh").run();
|
||||
if command.is_err() {
|
||||
entry_command_status_loop_sender.send_blocking(false).expect("The channel needs to be open.");
|
||||
} else {
|
||||
entry_command_status_loop_sender.send_blocking(true).expect("The channel needs to be open.");
|
||||
}
|
||||
}));
|
||||
}));
|
||||
|
||||
let cmd_err_dialog = adw::MessageDialog::builder()
|
||||
.body(t!("cmd_err_dialog_body"))
|
||||
.heading(t!("cmd_err_dialog_heading"))
|
||||
.transient_for(window)
|
||||
.build();
|
||||
cmd_err_dialog.add_response("cmd_err_dialog_ok", &t!("cmd_err_dialog_ok_label").to_string());
|
||||
|
||||
let entry_command_status_loop_context = MainContext::default();
|
||||
// The main loop executes the asynchronous block
|
||||
entry_command_status_loop_context.spawn_local(clone!(@weak cmd_err_dialog, @strong entry_command_status_loop_receiver => async move {
|
||||
while let Ok(state) = entry_command_status_loop_receiver.recv().await {
|
||||
if state == false {
|
||||
cmd_err_dialog.present();
|
||||
}
|
||||
}
|
||||
}));
|
||||
setup_steps_page_listbox.append(&entry_row)
|
||||
}
|
||||
|
||||
setup_steps_page_box.append(&setup_steps_page_listbox);
|
||||
|
||||
setup_steps_content_page_stack.add_titled(&setup_steps_page_scroll, Some("setup_steps_page"), &t!("setup_steps_page_title").to_string());
|
||||
}
|
157
src/welcome_content_page/contribute_page/mod.rs
Normal file
157
src/welcome_content_page/contribute_page/mod.rs
Normal file
@ -0,0 +1,157 @@
|
||||
// GTK crates
|
||||
use duct::cmd;
|
||||
use std::path::Path;
|
||||
use std::fs;
|
||||
use serde::Deserialize;
|
||||
use std::{thread, time};
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
use adw::prelude::*;
|
||||
use adw::*;
|
||||
use glib::*;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(PartialEq, Debug, Eq, Hash, Clone, Ord, PartialOrd, Deserialize)]
|
||||
struct setup_steps_entry {
|
||||
id: i32,
|
||||
title: String,
|
||||
subtitle: String,
|
||||
icon: String,
|
||||
button: String,
|
||||
command: String
|
||||
}
|
||||
|
||||
pub fn setup_steps_page(
|
||||
setup_steps_content_page_stack: >k::Stack,
|
||||
window: &adw::ApplicationWindow,
|
||||
internet_connected: &Rc<RefCell<bool>>
|
||||
) {
|
||||
let internet_connected_status = internet_connected.clone();
|
||||
|
||||
let (internet_loop_sender, internet_loop_receiver) = async_channel::unbounded();
|
||||
let internet_loop_sender = internet_loop_sender.clone();
|
||||
// The long running operation runs now in a separate thread
|
||||
gio::spawn_blocking(move || loop {
|
||||
thread::sleep(time::Duration::from_secs(1));
|
||||
internet_loop_sender
|
||||
.send_blocking(true)
|
||||
.expect("The channel needs to be open.");
|
||||
});
|
||||
|
||||
let setup_steps_page_box = gtk::Box::builder()
|
||||
.vexpand(true)
|
||||
.hexpand(true)
|
||||
.build();
|
||||
|
||||
let setup_steps_page_listbox = gtk::ListBox::builder()
|
||||
.margin_top(20)
|
||||
.margin_bottom(20)
|
||||
.margin_start(20)
|
||||
.margin_end(20)
|
||||
.vexpand(true)
|
||||
.hexpand(true)
|
||||
.build();
|
||||
setup_steps_page_listbox.add_css_class("boxed-list");
|
||||
|
||||
let setup_steps_page_scroll = gtk::ScrolledWindow::builder()
|
||||
// that puts items vertically
|
||||
.hexpand(true)
|
||||
.vexpand(true)
|
||||
.child(&setup_steps_page_box)
|
||||
.propagate_natural_width(true)
|
||||
.propagate_natural_height(true)
|
||||
.build();
|
||||
|
||||
let internet_loop_context = MainContext::default();
|
||||
// The main loop executes the asynchronous block
|
||||
internet_loop_context.spawn_local(
|
||||
clone!(@strong internet_connected_status, @weak setup_steps_page_box => async move {
|
||||
while let Ok(_state) = internet_loop_receiver.recv().await {
|
||||
if *internet_connected_status.borrow_mut() == true {
|
||||
setup_steps_page_box.set_sensitive(true);
|
||||
} else {
|
||||
setup_steps_page_box.set_sensitive(false);
|
||||
}
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
let mut json_array: Vec<setup_steps_entry> = Vec::new();
|
||||
let json_path = "/home/ward/builds/pkg-pika-welcome/data/config/setup_steps.json";
|
||||
let json_data = fs::read_to_string(json_path).expect("Unable to read json");
|
||||
let json_data: serde_json::Value = serde_json::from_str(&json_data).expect("JSON format invalid");
|
||||
if let serde_json::Value::Array(setup_steps) = &json_data["setup_steps"] {
|
||||
for setup_steps_entry in setup_steps {
|
||||
let setup_steps_entry_struct: setup_steps_entry = serde_json::from_value(setup_steps_entry.clone()).unwrap();
|
||||
json_array.push(setup_steps_entry_struct);
|
||||
}
|
||||
}
|
||||
|
||||
for setup_steps_entry in json_array {
|
||||
let (entry_command_status_loop_sender, entry_command_status_loop_receiver) = async_channel::unbounded();
|
||||
let entry_command_status_loop_sender: async_channel::Sender<bool> = entry_command_status_loop_sender.clone();
|
||||
|
||||
let entry_title = setup_steps_entry.title;
|
||||
let entry_subtitle = setup_steps_entry.subtitle;
|
||||
let entry_icon = setup_steps_entry.icon;
|
||||
let entry_button = setup_steps_entry.button;
|
||||
let entry_command = setup_steps_entry.command;
|
||||
let entry_row = adw::ActionRow::builder()
|
||||
.title(t!(&entry_title))
|
||||
.subtitle(t!(&entry_subtitle))
|
||||
.vexpand(true)
|
||||
.hexpand(true)
|
||||
.build();
|
||||
let entry_row_icon = gtk::Image::builder()
|
||||
.icon_name(entry_icon)
|
||||
.pixel_size(80)
|
||||
.vexpand(true)
|
||||
.valign(gtk::Align::Center)
|
||||
.build();
|
||||
let entry_row_button = gtk::Button::builder()
|
||||
.label(t!(&entry_button))
|
||||
.vexpand(true)
|
||||
.valign(gtk::Align::Center)
|
||||
.build();
|
||||
entry_row.add_prefix(&entry_row_icon);
|
||||
entry_row.add_suffix(&entry_row_button);
|
||||
|
||||
entry_row_button.connect_clicked(clone!(@strong entry_command, @weak window => move |_| {
|
||||
gio::spawn_blocking(clone!(@strong entry_command_status_loop_sender, @strong entry_command => move || {
|
||||
if Path::new("/tmp/pika-welcome-exec.sh").exists() {
|
||||
fs::remove_file("/tmp/pika-welcome-exec.sh").expect("Bad permissions on /tmp/pika-installer-gtk4-target-manual.txt");
|
||||
}
|
||||
fs::write("/tmp/pika-welcome-exec.sh", "#! /bin/bash\nset -e\n".to_owned() + &entry_command).expect("Unable to write file");
|
||||
let _ = cmd!("chmod", "+x", "/tmp/pika-welcome-exec.sh").read();
|
||||
let command = cmd!("/tmp/pika-welcome-exec.sh").run();
|
||||
if command.is_err() {
|
||||
entry_command_status_loop_sender.send_blocking(false).expect("The channel needs to be open.");
|
||||
} else {
|
||||
entry_command_status_loop_sender.send_blocking(true).expect("The channel needs to be open.");
|
||||
}
|
||||
}));
|
||||
}));
|
||||
|
||||
let cmd_err_dialog = adw::MessageDialog::builder()
|
||||
.body(t!("cmd_err_dialog_body"))
|
||||
.heading(t!("cmd_err_dialog_heading"))
|
||||
.transient_for(window)
|
||||
.build();
|
||||
cmd_err_dialog.add_response("cmd_err_dialog_ok", &t!("cmd_err_dialog_ok_label").to_string());
|
||||
|
||||
let entry_command_status_loop_context = MainContext::default();
|
||||
// The main loop executes the asynchronous block
|
||||
entry_command_status_loop_context.spawn_local(clone!(@weak cmd_err_dialog, @strong entry_command_status_loop_receiver => async move {
|
||||
while let Ok(state) = entry_command_status_loop_receiver.recv().await {
|
||||
if state == false {
|
||||
cmd_err_dialog.present();
|
||||
}
|
||||
}
|
||||
}));
|
||||
setup_steps_page_listbox.append(&entry_row)
|
||||
}
|
||||
|
||||
setup_steps_page_box.append(&setup_steps_page_listbox);
|
||||
|
||||
setup_steps_content_page_stack.add_titled(&setup_steps_page_scroll, Some("setup_steps_page"), &t!("setup_steps_page_title").to_string());
|
||||
}
|
157
src/welcome_content_page/look_and_feel_page/mod.rs
Normal file
157
src/welcome_content_page/look_and_feel_page/mod.rs
Normal file
@ -0,0 +1,157 @@
|
||||
// GTK crates
|
||||
use duct::cmd;
|
||||
use std::path::Path;
|
||||
use std::fs;
|
||||
use serde::Deserialize;
|
||||
use std::{thread, time};
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
use adw::prelude::*;
|
||||
use adw::*;
|
||||
use glib::*;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(PartialEq, Debug, Eq, Hash, Clone, Ord, PartialOrd, Deserialize)]
|
||||
struct setup_steps_entry {
|
||||
id: i32,
|
||||
title: String,
|
||||
subtitle: String,
|
||||
icon: String,
|
||||
button: String,
|
||||
command: String
|
||||
}
|
||||
|
||||
pub fn setup_steps_page(
|
||||
setup_steps_content_page_stack: >k::Stack,
|
||||
window: &adw::ApplicationWindow,
|
||||
internet_connected: &Rc<RefCell<bool>>
|
||||
) {
|
||||
let internet_connected_status = internet_connected.clone();
|
||||
|
||||
let (internet_loop_sender, internet_loop_receiver) = async_channel::unbounded();
|
||||
let internet_loop_sender = internet_loop_sender.clone();
|
||||
// The long running operation runs now in a separate thread
|
||||
gio::spawn_blocking(move || loop {
|
||||
thread::sleep(time::Duration::from_secs(1));
|
||||
internet_loop_sender
|
||||
.send_blocking(true)
|
||||
.expect("The channel needs to be open.");
|
||||
});
|
||||
|
||||
let setup_steps_page_box = gtk::Box::builder()
|
||||
.vexpand(true)
|
||||
.hexpand(true)
|
||||
.build();
|
||||
|
||||
let setup_steps_page_listbox = gtk::ListBox::builder()
|
||||
.margin_top(20)
|
||||
.margin_bottom(20)
|
||||
.margin_start(20)
|
||||
.margin_end(20)
|
||||
.vexpand(true)
|
||||
.hexpand(true)
|
||||
.build();
|
||||
setup_steps_page_listbox.add_css_class("boxed-list");
|
||||
|
||||
let setup_steps_page_scroll = gtk::ScrolledWindow::builder()
|
||||
// that puts items vertically
|
||||
.hexpand(true)
|
||||
.vexpand(true)
|
||||
.child(&setup_steps_page_box)
|
||||
.propagate_natural_width(true)
|
||||
.propagate_natural_height(true)
|
||||
.build();
|
||||
|
||||
let internet_loop_context = MainContext::default();
|
||||
// The main loop executes the asynchronous block
|
||||
internet_loop_context.spawn_local(
|
||||
clone!(@strong internet_connected_status, @weak setup_steps_page_box => async move {
|
||||
while let Ok(_state) = internet_loop_receiver.recv().await {
|
||||
if *internet_connected_status.borrow_mut() == true {
|
||||
setup_steps_page_box.set_sensitive(true);
|
||||
} else {
|
||||
setup_steps_page_box.set_sensitive(false);
|
||||
}
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
let mut json_array: Vec<setup_steps_entry> = Vec::new();
|
||||
let json_path = "/home/ward/builds/pkg-pika-welcome/data/config/setup_steps.json";
|
||||
let json_data = fs::read_to_string(json_path).expect("Unable to read json");
|
||||
let json_data: serde_json::Value = serde_json::from_str(&json_data).expect("JSON format invalid");
|
||||
if let serde_json::Value::Array(setup_steps) = &json_data["setup_steps"] {
|
||||
for setup_steps_entry in setup_steps {
|
||||
let setup_steps_entry_struct: setup_steps_entry = serde_json::from_value(setup_steps_entry.clone()).unwrap();
|
||||
json_array.push(setup_steps_entry_struct);
|
||||
}
|
||||
}
|
||||
|
||||
for setup_steps_entry in json_array {
|
||||
let (entry_command_status_loop_sender, entry_command_status_loop_receiver) = async_channel::unbounded();
|
||||
let entry_command_status_loop_sender: async_channel::Sender<bool> = entry_command_status_loop_sender.clone();
|
||||
|
||||
let entry_title = setup_steps_entry.title;
|
||||
let entry_subtitle = setup_steps_entry.subtitle;
|
||||
let entry_icon = setup_steps_entry.icon;
|
||||
let entry_button = setup_steps_entry.button;
|
||||
let entry_command = setup_steps_entry.command;
|
||||
let entry_row = adw::ActionRow::builder()
|
||||
.title(t!(&entry_title))
|
||||
.subtitle(t!(&entry_subtitle))
|
||||
.vexpand(true)
|
||||
.hexpand(true)
|
||||
.build();
|
||||
let entry_row_icon = gtk::Image::builder()
|
||||
.icon_name(entry_icon)
|
||||
.pixel_size(80)
|
||||
.vexpand(true)
|
||||
.valign(gtk::Align::Center)
|
||||
.build();
|
||||
let entry_row_button = gtk::Button::builder()
|
||||
.label(t!(&entry_button))
|
||||
.vexpand(true)
|
||||
.valign(gtk::Align::Center)
|
||||
.build();
|
||||
entry_row.add_prefix(&entry_row_icon);
|
||||
entry_row.add_suffix(&entry_row_button);
|
||||
|
||||
entry_row_button.connect_clicked(clone!(@strong entry_command, @weak window => move |_| {
|
||||
gio::spawn_blocking(clone!(@strong entry_command_status_loop_sender, @strong entry_command => move || {
|
||||
if Path::new("/tmp/pika-welcome-exec.sh").exists() {
|
||||
fs::remove_file("/tmp/pika-welcome-exec.sh").expect("Bad permissions on /tmp/pika-installer-gtk4-target-manual.txt");
|
||||
}
|
||||
fs::write("/tmp/pika-welcome-exec.sh", "#! /bin/bash\nset -e\n".to_owned() + &entry_command).expect("Unable to write file");
|
||||
let _ = cmd!("chmod", "+x", "/tmp/pika-welcome-exec.sh").read();
|
||||
let command = cmd!("/tmp/pika-welcome-exec.sh").run();
|
||||
if command.is_err() {
|
||||
entry_command_status_loop_sender.send_blocking(false).expect("The channel needs to be open.");
|
||||
} else {
|
||||
entry_command_status_loop_sender.send_blocking(true).expect("The channel needs to be open.");
|
||||
}
|
||||
}));
|
||||
}));
|
||||
|
||||
let cmd_err_dialog = adw::MessageDialog::builder()
|
||||
.body(t!("cmd_err_dialog_body"))
|
||||
.heading(t!("cmd_err_dialog_heading"))
|
||||
.transient_for(window)
|
||||
.build();
|
||||
cmd_err_dialog.add_response("cmd_err_dialog_ok", &t!("cmd_err_dialog_ok_label").to_string());
|
||||
|
||||
let entry_command_status_loop_context = MainContext::default();
|
||||
// The main loop executes the asynchronous block
|
||||
entry_command_status_loop_context.spawn_local(clone!(@weak cmd_err_dialog, @strong entry_command_status_loop_receiver => async move {
|
||||
while let Ok(state) = entry_command_status_loop_receiver.recv().await {
|
||||
if state == false {
|
||||
cmd_err_dialog.present();
|
||||
}
|
||||
}
|
||||
}));
|
||||
setup_steps_page_listbox.append(&entry_row)
|
||||
}
|
||||
|
||||
setup_steps_page_box.append(&setup_steps_page_listbox);
|
||||
|
||||
setup_steps_content_page_stack.add_titled(&setup_steps_page_scroll, Some("setup_steps_page"), &t!("setup_steps_page_title").to_string());
|
||||
}
|
@ -62,6 +62,16 @@ pub fn welcome_content_page(window: &adw::ApplicationWindow, content_box: >k::
|
||||
.icon_name("dialog-information-symbolic")
|
||||
.build();
|
||||
|
||||
let mut json_array: Vec<GString> = Vec::new();
|
||||
let json_path = "/home/ward/builds/pkg-pika-welcome/data/config/credits.json";
|
||||
let json_data = std::fs::read_to_string(json_path).expect("Unable to read json");
|
||||
let json_data: serde_json::Value = serde_json::from_str(&json_data).expect("JSON format invalid");
|
||||
if let serde_json::Value::Array(developers) = &json_data["developers"] {
|
||||
for developer in developers {
|
||||
json_array.push(developer["dev"].as_str().to_owned().unwrap().into())
|
||||
}
|
||||
}
|
||||
|
||||
let credits_window = adw::AboutWindow::builder()
|
||||
.application_icon(APP_ICON)
|
||||
.application_name(t!("app_name"))
|
||||
@ -69,6 +79,7 @@ pub fn welcome_content_page(window: &adw::ApplicationWindow, content_box: >k::
|
||||
.version(VERSION)
|
||||
.hide_on_close(true)
|
||||
.developer_name(t!("app_dev"))
|
||||
.developers(json_array)
|
||||
.issue_url(APP_GITHUB.to_owned() + "/issues")
|
||||
.build();
|
||||
|
||||
|
157
src/welcome_content_page/troubleshoot_page/mod.rs
Normal file
157
src/welcome_content_page/troubleshoot_page/mod.rs
Normal file
@ -0,0 +1,157 @@
|
||||
// GTK crates
|
||||
use duct::cmd;
|
||||
use std::path::Path;
|
||||
use std::fs;
|
||||
use serde::Deserialize;
|
||||
use std::{thread, time};
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
use adw::prelude::*;
|
||||
use adw::*;
|
||||
use glib::*;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(PartialEq, Debug, Eq, Hash, Clone, Ord, PartialOrd, Deserialize)]
|
||||
struct setup_steps_entry {
|
||||
id: i32,
|
||||
title: String,
|
||||
subtitle: String,
|
||||
icon: String,
|
||||
button: String,
|
||||
command: String
|
||||
}
|
||||
|
||||
pub fn setup_steps_page(
|
||||
setup_steps_content_page_stack: >k::Stack,
|
||||
window: &adw::ApplicationWindow,
|
||||
internet_connected: &Rc<RefCell<bool>>
|
||||
) {
|
||||
let internet_connected_status = internet_connected.clone();
|
||||
|
||||
let (internet_loop_sender, internet_loop_receiver) = async_channel::unbounded();
|
||||
let internet_loop_sender = internet_loop_sender.clone();
|
||||
// The long running operation runs now in a separate thread
|
||||
gio::spawn_blocking(move || loop {
|
||||
thread::sleep(time::Duration::from_secs(1));
|
||||
internet_loop_sender
|
||||
.send_blocking(true)
|
||||
.expect("The channel needs to be open.");
|
||||
});
|
||||
|
||||
let setup_steps_page_box = gtk::Box::builder()
|
||||
.vexpand(true)
|
||||
.hexpand(true)
|
||||
.build();
|
||||
|
||||
let setup_steps_page_listbox = gtk::ListBox::builder()
|
||||
.margin_top(20)
|
||||
.margin_bottom(20)
|
||||
.margin_start(20)
|
||||
.margin_end(20)
|
||||
.vexpand(true)
|
||||
.hexpand(true)
|
||||
.build();
|
||||
setup_steps_page_listbox.add_css_class("boxed-list");
|
||||
|
||||
let setup_steps_page_scroll = gtk::ScrolledWindow::builder()
|
||||
// that puts items vertically
|
||||
.hexpand(true)
|
||||
.vexpand(true)
|
||||
.child(&setup_steps_page_box)
|
||||
.propagate_natural_width(true)
|
||||
.propagate_natural_height(true)
|
||||
.build();
|
||||
|
||||
let internet_loop_context = MainContext::default();
|
||||
// The main loop executes the asynchronous block
|
||||
internet_loop_context.spawn_local(
|
||||
clone!(@strong internet_connected_status, @weak setup_steps_page_box => async move {
|
||||
while let Ok(_state) = internet_loop_receiver.recv().await {
|
||||
if *internet_connected_status.borrow_mut() == true {
|
||||
setup_steps_page_box.set_sensitive(true);
|
||||
} else {
|
||||
setup_steps_page_box.set_sensitive(false);
|
||||
}
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
let mut json_array: Vec<setup_steps_entry> = Vec::new();
|
||||
let json_path = "/home/ward/builds/pkg-pika-welcome/data/config/setup_steps.json";
|
||||
let json_data = fs::read_to_string(json_path).expect("Unable to read json");
|
||||
let json_data: serde_json::Value = serde_json::from_str(&json_data).expect("JSON format invalid");
|
||||
if let serde_json::Value::Array(setup_steps) = &json_data["setup_steps"] {
|
||||
for setup_steps_entry in setup_steps {
|
||||
let setup_steps_entry_struct: setup_steps_entry = serde_json::from_value(setup_steps_entry.clone()).unwrap();
|
||||
json_array.push(setup_steps_entry_struct);
|
||||
}
|
||||
}
|
||||
|
||||
for setup_steps_entry in json_array {
|
||||
let (entry_command_status_loop_sender, entry_command_status_loop_receiver) = async_channel::unbounded();
|
||||
let entry_command_status_loop_sender: async_channel::Sender<bool> = entry_command_status_loop_sender.clone();
|
||||
|
||||
let entry_title = setup_steps_entry.title;
|
||||
let entry_subtitle = setup_steps_entry.subtitle;
|
||||
let entry_icon = setup_steps_entry.icon;
|
||||
let entry_button = setup_steps_entry.button;
|
||||
let entry_command = setup_steps_entry.command;
|
||||
let entry_row = adw::ActionRow::builder()
|
||||
.title(t!(&entry_title))
|
||||
.subtitle(t!(&entry_subtitle))
|
||||
.vexpand(true)
|
||||
.hexpand(true)
|
||||
.build();
|
||||
let entry_row_icon = gtk::Image::builder()
|
||||
.icon_name(entry_icon)
|
||||
.pixel_size(80)
|
||||
.vexpand(true)
|
||||
.valign(gtk::Align::Center)
|
||||
.build();
|
||||
let entry_row_button = gtk::Button::builder()
|
||||
.label(t!(&entry_button))
|
||||
.vexpand(true)
|
||||
.valign(gtk::Align::Center)
|
||||
.build();
|
||||
entry_row.add_prefix(&entry_row_icon);
|
||||
entry_row.add_suffix(&entry_row_button);
|
||||
|
||||
entry_row_button.connect_clicked(clone!(@strong entry_command, @weak window => move |_| {
|
||||
gio::spawn_blocking(clone!(@strong entry_command_status_loop_sender, @strong entry_command => move || {
|
||||
if Path::new("/tmp/pika-welcome-exec.sh").exists() {
|
||||
fs::remove_file("/tmp/pika-welcome-exec.sh").expect("Bad permissions on /tmp/pika-installer-gtk4-target-manual.txt");
|
||||
}
|
||||
fs::write("/tmp/pika-welcome-exec.sh", "#! /bin/bash\nset -e\n".to_owned() + &entry_command).expect("Unable to write file");
|
||||
let _ = cmd!("chmod", "+x", "/tmp/pika-welcome-exec.sh").read();
|
||||
let command = cmd!("/tmp/pika-welcome-exec.sh").run();
|
||||
if command.is_err() {
|
||||
entry_command_status_loop_sender.send_blocking(false).expect("The channel needs to be open.");
|
||||
} else {
|
||||
entry_command_status_loop_sender.send_blocking(true).expect("The channel needs to be open.");
|
||||
}
|
||||
}));
|
||||
}));
|
||||
|
||||
let cmd_err_dialog = adw::MessageDialog::builder()
|
||||
.body(t!("cmd_err_dialog_body"))
|
||||
.heading(t!("cmd_err_dialog_heading"))
|
||||
.transient_for(window)
|
||||
.build();
|
||||
cmd_err_dialog.add_response("cmd_err_dialog_ok", &t!("cmd_err_dialog_ok_label").to_string());
|
||||
|
||||
let entry_command_status_loop_context = MainContext::default();
|
||||
// The main loop executes the asynchronous block
|
||||
entry_command_status_loop_context.spawn_local(clone!(@weak cmd_err_dialog, @strong entry_command_status_loop_receiver => async move {
|
||||
while let Ok(state) = entry_command_status_loop_receiver.recv().await {
|
||||
if state == false {
|
||||
cmd_err_dialog.present();
|
||||
}
|
||||
}
|
||||
}));
|
||||
setup_steps_page_listbox.append(&entry_row)
|
||||
}
|
||||
|
||||
setup_steps_page_box.append(&setup_steps_page_listbox);
|
||||
|
||||
setup_steps_content_page_stack.add_titled(&setup_steps_page_scroll, Some("setup_steps_page"), &t!("setup_steps_page_title").to_string());
|
||||
}
|
Loading…
Reference in New Issue
Block a user