diff --git a/data/com.github.pikaos-linux.pikafirstsetup.gschema.xml b/data/com.github.pikaos-linux.pikafirstsetup.gschema.xml new file mode 100644 index 0000000..ca66877 --- /dev/null +++ b/data/com.github.pikaos-linux.pikafirstsetup.gschema.xml @@ -0,0 +1,17 @@ + + + + + 1200 + Default window width + + + 600 + Default window height + + + false + Default window maximized behaviour + + + diff --git a/src/first_setup/first_setup.rs b/src/first_setup/first_setup.rs new file mode 100644 index 0000000..0c4fb0c --- /dev/null +++ b/src/first_setup/first_setup.rs @@ -0,0 +1,70 @@ +// GTK crates +/// Use all gtk4 libraries (gtk4 -> gtk because cargo) +/// Use all libadwaita libraries (libadwaita -> adw because cargo) +use gtk::prelude::*; +use gtk::*; +use adw::prelude::*; +use adw::*; +use adw::ffi::ADW_TOOLBAR_FLAT; +use glib::*; +use gdk::Display; + +// +use std::cell::RefCell; +use std::rc::Rc; +use crate::connection_check::check_internet_connection; + +// carousel crates +use crate::first_setup::initial_carousel::initial_carousel; +use crate::first_setup::internet_carousel::internet_carousel; +use crate::first_setup::update_carousel::update_carousel; + +pub fn first_setup(window: &adw::ApplicationWindow) { + + let first_setup_carousel = adw::Carousel::builder() + .allow_long_swipes(false) + .allow_mouse_drag(false) + .allow_scroll_wheel(false) + .interactive(false) + .vexpand(true) + .hexpand(true) + .build(); + + let first_setup_carousel_indicator = adw::CarouselIndicatorDots::builder() + .carousel(&first_setup_carousel) + .build(); + + let first_setup_window_headerbar_back_button = gtk::Button::builder() + .label("Back") + .build(); + + let first_setup_window_headerbar = adw::HeaderBar::builder() + .show_start_title_buttons(true) + .title_widget(&first_setup_carousel_indicator) + .build(); + + let first_setup_window_toolbarview = adw::ToolbarView::builder() + .top_bar_style(ToolbarStyle::Flat) + .content(&first_setup_carousel) + .build(); + + let internet_connected = Rc::new(RefCell::new(false)); + + first_setup_window_headerbar.pack_start(&first_setup_window_headerbar_back_button); + first_setup_window_toolbarview.add_top_bar(&first_setup_window_headerbar); + + first_setup_window_headerbar_back_button.connect_clicked(clone!(@weak first_setup_carousel => move |_| { + let first_setup_prev_page = first_setup_carousel.position() - 1.0; + first_setup_carousel.scroll_to(&first_setup_carousel.nth_page(first_setup_prev_page as u32), true) + })); + + // CAROUSELS + + // Initial Carousel + initial_carousel(&first_setup_carousel); + internet_carousel(&first_setup_carousel, &internet_connected); + update_carousel(&first_setup_carousel, &internet_connected); + + // Add file to window + window.set_content(Some(&first_setup_window_toolbarview)) +} \ No newline at end of file diff --git a/src/first_setup/initial_carousel.rs b/src/first_setup/initial_carousel.rs new file mode 100644 index 0000000..b2498b0 --- /dev/null +++ b/src/first_setup/initial_carousel.rs @@ -0,0 +1,44 @@ +// GTK crates +/// Use all gtk4 libraries (gtk4 -> gtk because cargo) +/// Use all libadwaita libraries (libadwaita -> adw because cargo) +use gtk::prelude::*; +use gtk::*; +use adw::prelude::*; +use adw::*; +use glib::*; +use gdk::Display; + +pub fn initial_carousel(first_setup_carousel: &adw::Carousel) { + let first_setup_initial_box = gtk::Box::builder() + // that puts items vertically + .orientation(Orientation::Vertical) + .vexpand(true) + .valign(Align::Center) + .hexpand(true) + .vexpand(true) + .build(); + + let first_setup_initial_box_text = adw::StatusPage::builder() + .icon_name("debian-swirl") + .title("Welcome") + .description("This wizard will help you finish your PikaOS installation.") + .build(); + first_setup_initial_box_text.add_css_class("compact"); + + let first_setup_start_button = gtk::Button::builder() + .label("Let's Start") + .halign(Align::Center) + .build(); + + first_setup_start_button.add_css_class("suggested-action"); + first_setup_start_button.add_css_class("pill"); + + first_setup_initial_box.append(&first_setup_initial_box_text); + first_setup_initial_box.append(&first_setup_start_button); + + first_setup_carousel.append(&first_setup_initial_box); + + first_setup_start_button.connect_clicked(clone!(@weak first_setup_carousel => move |_| { + first_setup_carousel.scroll_to(&first_setup_carousel.nth_page(1), true) + })); +} \ No newline at end of file diff --git a/src/first_setup/internet_carousel.rs b/src/first_setup/internet_carousel.rs new file mode 100644 index 0000000..7b5fb9a --- /dev/null +++ b/src/first_setup/internet_carousel.rs @@ -0,0 +1,133 @@ +// GTK crates +/// Use all gtk4 libraries (gtk4 -> gtk because cargo) +/// Use all libadwaita libraries (libadwaita -> adw because cargo) +use gtk::prelude::*; +use gtk::*; +use adw::prelude::*; +use adw::*; +use glib::*; +use gdk::Display; + +//use crate::check_internet_connection; +use std::process::Command; +use std::cell::RefCell; +use std::rc::Rc; +use std::borrow::Borrow as the_rc_borrow; + +pub fn internet_carousel(first_setup_carousel: &adw::Carousel, internet_connected: &Rc>) { + + 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 { + //match check_internet_connection() { + // Ok(_) => { + // internet_loop_sender.send_blocking(true).expect("The channel needs to be open."); + // } + // Err(_) => { + // internet_loop_sender.send_blocking(false).expect("The channel needs to be open."); + // } + //} + let check_internet_connection_cli = Command::new("ping") + .arg("ppa.pika-os.com") + .arg("-c 1") + .output() + .expect("failed to execute process"); + if check_internet_connection_cli.status.success() { + internet_loop_sender.send_blocking(true).expect("The channel needs to be open."); + } else { + internet_loop_sender.send_blocking(false).expect("The channel needs to be open."); + } + } + }); + + let first_setup_internet_box = gtk::Box::builder() + // that puts items vertically + .orientation(Orientation::Vertical) + .hexpand(true) + .vexpand(true) + .margin_end(15) + .margin_start(15) + .margin_bottom(15) + .margin_top(15) + .build(); + + let first_setup_internet_box_text = adw::StatusPage::builder() + .icon_name("network-cellular-acquiring") + .title("Internet") + .description("Checking Internet Connection...") + .hexpand(true) + .vexpand(true) + .valign(Align::Start) + .build(); + first_setup_internet_box_text.add_css_class("compact"); + + let internet_skip_button = gtk::Button::builder() + .label("Skip") + .halign(Align::Center) + .sensitive(false) + .build(); + + internet_skip_button.add_css_class("destructive-action"); + internet_skip_button.add_css_class("pill"); + + let internet_next_button = gtk::Button::builder() + .label("Next") + .halign(Align::Center) + .sensitive(false) + .build(); + + internet_next_button.add_css_class("suggested-action"); + internet_next_button.add_css_class("pill"); + + let internet_buttons_box = gtk::Box::builder() + .orientation(Orientation::Horizontal) + .halign(Align::Center) + .valign(Align::End) + .hexpand(true) + .margin_end(15) + .margin_start(15) + .margin_bottom(15) + .margin_top(15) + .spacing(80) + .build(); + + internet_buttons_box.append(&internet_skip_button); + internet_buttons_box.append(&internet_next_button); + + first_setup_internet_box.append(&first_setup_internet_box_text); + first_setup_internet_box.append(&internet_buttons_box); + + first_setup_carousel.append(&first_setup_internet_box); + + let internet_connected_status = internet_connected.clone(); + + let internet_loop_context = MainContext::default(); + // The main loop executes the asynchronous block + internet_loop_context.spawn_local(clone!(@weak internet_skip_button, @weak internet_next_button, @weak first_setup_internet_box_text => async move { + while let Ok(state) = internet_loop_receiver.recv().await { + if state == true { + internet_skip_button.set_sensitive(false); + internet_next_button.set_sensitive(true); + first_setup_internet_box_text.set_description(Some("Device connected to Internet Successfully!")); + first_setup_internet_box_text.set_icon_name(Some("network-cellular-signal-excellent")); + *internet_connected_status.borrow_mut()=true; + } else { + internet_next_button.set_sensitive(false); + internet_skip_button.set_sensitive(true); + first_setup_internet_box_text.set_description(Some("No internet Connection!")); + first_setup_internet_box_text.set_icon_name(Some("network-cellular-offline")); + *internet_connected_status.borrow_mut()=false; + } + } + })); + + internet_next_button.connect_clicked(clone!(@weak first_setup_carousel => move |_| { + first_setup_carousel.scroll_to(&first_setup_carousel.nth_page(2), true); + })); + + internet_skip_button.connect_clicked(clone!(@weak first_setup_carousel => move |_| { + first_setup_carousel.scroll_to(&first_setup_carousel.nth_page(2), true); + })); +} \ No newline at end of file diff --git a/src/first_setup/mod.rs b/src/first_setup/mod.rs new file mode 100644 index 0000000..bf09ffb --- /dev/null +++ b/src/first_setup/mod.rs @@ -0,0 +1,5 @@ +pub mod first_setup; +pub mod initial_carousel; +pub mod internet_carousel; + +pub mod update_carousel; \ No newline at end of file