diff --git a/Cargo.toml b/Cargo.toml index 6ee1c40..3450370 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,22 +12,10 @@ path = "src/gui/main.rs" name = "pika_unixsocket_tools" path = "src/pika_unixsocket_tools/lib.rs" -[[bin]] -name = "debug_server_update_percent" -path = "src/debug_server/update_percent.rs" - -[[bin]] -name = "debug_server_update_status" -path = "src/debug_server/update_status.rs" - [[bin]] name = "apt_update" path = "src/apt_update/main.rs" -[[bin]] -name = "apt_get_upgradable" -path = "src/apt_get_upgradable/main.rs" - [dependencies] adw = { version = "0.5.3", package = "libadwaita", features = ["v1_4"] } gtk = { version = "0.7.3", package = "gtk4", features = ["v4_12"] } diff --git a/src/apt_get_upgradable/main.rs b/src/apt_get_upgradable/main.rs deleted file mode 100644 index ec064cf..0000000 --- a/src/apt_get_upgradable/main.rs +++ /dev/null @@ -1,55 +0,0 @@ -use rust_apt::new_cache; -use rust_apt::cache::*; -use tokio::net::{UnixStream}; -use tokio::io::{AsyncReadExt, AsyncWriteExt}; - -use serde::{Serialize}; -#[derive(Serialize)] -struct AptPackageSocket { - name: String, - arch: String, - installed_version: String, - candidate_version: String -} -#[tokio::main] -async fn main() { - // Create upgradable list cache - let upgradable_cache = new_cache!().unwrap(); - - // Create pack sort from upgradable_cache - let upgradable_sort = PackageSort::default().upgradable().names(); - - for pkg in upgradable_cache.packages(&upgradable_sort) { - let package_struct = AptPackageSocket { - name: pkg.name().to_string(), - arch: pkg.arch().to_string(), - installed_version: pkg.installed().unwrap().version().to_string(), - candidate_version: pkg.candidate().unwrap().version().to_string() - }; - - // Path to the Unix socket file - let socket_path = "/tmp/pika_apt_get_upgradable.sock"; - - // Connect to the Unix socket - let mut stream = UnixStream::connect(socket_path).await.expect("Could not connect to server"); - - let message = serde_json::to_string(&package_struct).unwrap(); - // Send the message to the server - stream.write_all(message.as_bytes()).await.expect("Failed to write to stream"); - - // Buffer to store the server's response - let mut buffer = [0; 2024]; - - // Read the response from the server - match stream.read(&mut buffer).await { - Ok(size) => { - // Print the received response - //println!("Response from Server on GTK4: {}", String::from_utf8_lossy(&buffer[..size])); - } - Err(e) => { - // Print error message if reading fails - //eprintln!("Failed to read Server on GTK4 with Error: {}", e); - } - } - } -} \ No newline at end of file diff --git a/src/debug_server/get_upgradable.rs b/src/debug_server/get_upgradable.rs deleted file mode 100644 index 5f9ee9e..0000000 --- a/src/debug_server/get_upgradable.rs +++ /dev/null @@ -1,55 +0,0 @@ -use tokio::net::{UnixListener, UnixStream}; -use tokio::io::{AsyncReadExt, AsyncWriteExt}; -use tokio::task; -use std::path::Path; -use std::fs; - -// Entry point of the server binary -#[tokio::main] -async fn main() { - // Path to the Unix socket file - let pika_apt_update_socket_path = "/tmp/pika_apt_get_upgradable.sock"; - - // Remove the socket file if it already exists - if Path::new(pika_apt_update_socket_path).exists() { - fs::remove_file(pika_apt_update_socket_path).expect("Could not remove existing socket file"); - } - - // Bind the Unix listener to the socket path - let pika_apt_update_listener = UnixListener::bind(pika_apt_update_socket_path).expect("Could not bind"); - - println!("Server listening on {}", pika_apt_update_socket_path); - - // Loop to accept incoming connections - loop { - // Accept an incoming connection - match pika_apt_update_listener.accept().await { - Ok((stream, _)) => { - // Handle the connection in a separate task - task::spawn(handle_client(stream)); - } - Err(e) => { - // Print error message if a connection fails - eprintln!("pika_apt_update: Connection failed: {}", e); - } - } - } -} - -// Function to handle a single client connection -async fn handle_client(mut stream: UnixStream) { - // Buffer to store incoming data - let mut buffer = [0; 1024]; - - // Read data from the stream - match stream.read(&mut buffer).await { - Ok(size) => { - // Print the received message - println!("pika_apt_update: Received: {}", String::from_utf8_lossy(&buffer[..size])); - } - Err(e) => { - // Print error message if reading fails - eprintln!("Failed to read from stream: {}", e); - } - } -} diff --git a/src/debug_server/update_percent.rs b/src/debug_server/update_percent.rs deleted file mode 100644 index cc41185..0000000 --- a/src/debug_server/update_percent.rs +++ /dev/null @@ -1,55 +0,0 @@ -use tokio::net::{UnixListener, UnixStream}; -use tokio::io::{AsyncReadExt, AsyncWriteExt}; -use tokio::task; -use std::path::Path; -use std::fs; - -// Entry point of the server binary -#[tokio::main] -async fn main() { - // Path to the Unix socket file - let pika_apt_update_socket_path = "/tmp/pika_apt_update_percent.sock"; - - // Remove the socket file if it already exists - if Path::new(pika_apt_update_socket_path).exists() { - fs::remove_file(pika_apt_update_socket_path).expect("Could not remove existing socket file"); - } - - // Bind the Unix listener to the socket path - let pika_apt_update_listener = UnixListener::bind(pika_apt_update_socket_path).expect("Could not bind"); - - println!("Server listening on {}", pika_apt_update_socket_path); - - // Loop to accept incoming connections - loop { - // Accept an incoming connection - match pika_apt_update_listener.accept().await { - Ok((stream, _)) => { - // Handle the connection in a separate task - task::spawn(handle_client(stream)); - } - Err(e) => { - // Print error message if a connection fails - eprintln!("pika_apt_update: Connection failed: {}", e); - } - } - } -} - -// Function to handle a single client connection -async fn handle_client(mut stream: UnixStream) { - // Buffer to store incoming data - let mut buffer = [0; 1024]; - - // Read data from the stream - match stream.read(&mut buffer).await { - Ok(size) => { - // Print the received message - println!("pika_apt_update: Received: {}", String::from_utf8_lossy(&buffer[..size])); - } - Err(e) => { - // Print error message if reading fails - eprintln!("Failed to read from stream: {}", e); - } - } -} diff --git a/src/debug_server/update_status.rs b/src/debug_server/update_status.rs deleted file mode 100644 index d80432b..0000000 --- a/src/debug_server/update_status.rs +++ /dev/null @@ -1,55 +0,0 @@ -use tokio::net::{UnixListener, UnixStream}; -use tokio::io::{AsyncReadExt, AsyncWriteExt}; -use tokio::task; -use std::path::Path; -use std::fs; - -// Entry point of the server binary -#[tokio::main] -async fn main() { - // Path to the Unix socket file - let pika_apt_update_socket_path = "/tmp/pika_apt_update_status.sock"; - - // Remove the socket file if it already exists - if Path::new(pika_apt_update_socket_path).exists() { - fs::remove_file(pika_apt_update_socket_path).expect("Could not remove existing socket file"); - } - - // Bind the Unix listener to the socket path - let pika_apt_update_listener = UnixListener::bind(pika_apt_update_socket_path).expect("Could not bind"); - - println!("Server listening on {}", pika_apt_update_socket_path); - - // Loop to accept incoming connections - loop { - // Accept an incoming connection - match pika_apt_update_listener.accept().await { - Ok((stream, _)) => { - // Handle the connection in a separate task - task::spawn(handle_client(stream)); - } - Err(e) => { - // Print error message if a connection fails - eprintln!("pika_apt_update: Connection failed: {}", e); - } - } - } -} - -// Function to handle a single client connection -async fn handle_client(mut stream: UnixStream) { - // Buffer to store incoming data - let mut buffer = [0; 1024]; - - // Read data from the stream - match stream.read(&mut buffer).await { - Ok(size) => { - // Print the received message - println!("pika_apt_update: Received: {}", String::from_utf8_lossy(&buffer[..size])); - } - Err(e) => { - // Print error message if reading fails - eprintln!("Failed to read from stream: {}", e); - } - } -} diff --git a/src/gui/apt_package_row/imp.rs b/src/gui/apt_package_row/imp.rs new file mode 100644 index 0000000..072f1bd --- /dev/null +++ b/src/gui/apt_package_row/imp.rs @@ -0,0 +1,173 @@ +use std::{cell::RefCell, default, sync::OnceLock}; + +use adw::*; +use adw::{prelude::*, subclass::prelude::*}; +use glib::{subclass::Signal, Properties}; +use gtk::{Align, glib, Orientation, SizeGroupMode, SelectionMode}; +use crate::apt_update_page::AptPackageSocket; + +// ANCHOR: custom_button +// Object holding the state +#[derive(Properties, Default)] +#[properties(wrapper_type = super::AptPackageRow)] +pub struct AptPackageRow { + #[property(get, set)] + package_name: RefCell, + #[property(get, set)] + package_arch: RefCell, + #[property(get, set)] + package_installed_version: RefCell, + #[property(get, set)] + package_candidate_version: RefCell +} +// ANCHOR_END: custom_button + +// The central trait for subclassing a GObject +#[glib::object_subclass] +impl ObjectSubclass for AptPackageRow { + const NAME: &'static str = "AptPackageRow"; + type Type = super::AptPackageRow; + type ParentType = adw::ActionRow; +} + +// ANCHOR: object_impl +// Trait shared by all GObjects +#[glib::derived_properties] +impl ObjectImpl for AptPackageRow { + fn signals() -> &'static [Signal] { + static SIGNALS: OnceLock> = OnceLock::new(); + SIGNALS.get_or_init(|| vec![Signal::builder("row-deleted").build()]) + } + fn constructed(&self) { + self.parent_constructed(); + + // Bind label to number + // `SYNC_CREATE` ensures that the label will be immediately set + let obj = self.obj(); + + let prefix_box = gtk::Box::new(Orientation::Horizontal, 0); + obj.add_prefix(&prefix_box); + + obj.add_prefix(&create_version_badge("1.0-100-pika1".to_string(), "1.1-101-pika1".to_string())); + + // Bind label to number + // `SYNC_CREATE` ensures that the label will be immediately set + //let obj = self.obj(); + //obj.bind_property("package", &basic_expander_row_package_label, "label") + // .sync_create() + // .bidirectional() + // .build(); + } +} +// Trait shared by all widgets +impl WidgetImpl for AptPackageRow {} + +// Trait shared by all buttons +// Trait shared by all buttons + +impl ListBoxRowImpl for AptPackageRow {} +impl PreferencesRowImpl for AptPackageRow {} +impl ActionRowImpl for AptPackageRow {} + +fn create_version_badge(installed_version: String, candidate_version: String) -> gtk::ListBox { + let (base_version, installed_diff, candidate_diff) = get_diff_by_prefix(installed_version, candidate_version); + + let badge_box = gtk::Box::builder().build(); + + let group_size = gtk::SizeGroup::new(SizeGroupMode::Both); + + let installed_version_box = gtk::Box::new(Orientation::Horizontal, 0); + + let installed_version_base_version_label = gtk::Label::builder() + .label(&base_version) + .margin_start(5) + .margin_end(5) + .margin_bottom(1) + .margin_top(1) + .valign(Align::Center) + .halign(Align::Start) + .hexpand(false) + .vexpand(true) + .build(); + + let installed_diff_label = gtk::Label::builder() + .label(installed_diff) + .margin_start(5) + .margin_end(5) + .margin_bottom(1) + .margin_top(1) + .valign(Align::Center) + .halign(Align::Start) + .hexpand(false) + .vexpand(true) + .build(); + installed_diff_label.add_css_class("destructive-color-text"); + + installed_version_box.append(&installed_version_base_version_label.clone()); + installed_version_box.append(&installed_diff_label); + group_size.add_widget(&installed_version_box); + + let label_seprator = gtk::Separator::builder().build(); + + let candidate_version_box = gtk::Box::new(Orientation::Horizontal, 0); + + let candidate_version_base_version_label = gtk::Label::builder() + .label(base_version) + .margin_start(5) + .margin_end(5) + .margin_bottom(1) + .margin_top(1) + .valign(Align::Center) + .halign(Align::Start) + .hexpand(false) + .vexpand(true) + .build(); + + let candidate_diff_label = gtk::Label::builder() + .label(candidate_diff) + .margin_start(5) + .margin_end(5) + .margin_bottom(1) + .margin_top(1) + .valign(Align::Center) + .halign(Align::Start) + .hexpand(false) + .vexpand(true) + .build(); + candidate_diff_label.add_css_class("success-color-text"); + + candidate_version_box.append(&candidate_version_base_version_label); + candidate_version_box.append(&candidate_diff_label); + group_size.add_widget(&candidate_diff_label); + + badge_box.append(&installed_version_box); + badge_box.append(&label_seprator); + badge_box.append(&candidate_version_box); + + let boxedlist = gtk::ListBox::builder() + .selection_mode(SelectionMode::None) + .halign(Align::Center) + .valign(Align::End) + .margin_start(5) + .margin_end(5) + .margin_bottom(5) + .margin_top(5) + .build(); + + boxedlist.add_css_class("boxed-list"); + boxedlist.append(&badge_box); + boxedlist +} + +pub fn get_diff_by_prefix(xs: String, ys: String) -> (String, String, String) { + let mut count = String::new(); + for (x,y) in xs.chars().zip(ys.chars()) { + if x == y { + count.push(x) + } else { + break + } + } + let count_clone0 = count.clone(); + return(count_clone0, xs.trim_start_matches(&count.as_str()).to_string(), ys.trim_start_matches(&count.as_str()).to_string()) +} \ No newline at end of file diff --git a/src/gui/apt_package_row/mod.rs b/src/gui/apt_package_row/mod.rs new file mode 100644 index 0000000..d794a8e --- /dev/null +++ b/src/gui/apt_package_row/mod.rs @@ -0,0 +1,34 @@ +mod imp; + +use glib::Object; +use gtk::glib; +use crate::apt_update_page::AptPackageSocket; + +glib::wrapper! { + pub struct AptPackageRow(ObjectSubclass) + @extends adw::ActionRow, gtk::Widget, gtk::ListBoxRow, adw::PreferencesRow, + @implements gtk::Accessible, gtk::Actionable, gtk::Buildable, gtk::ConstraintTarget; +} + +impl AptPackageRow { + pub fn new(package: AptPackageSocket) -> Self { + Object::builder() + .property("package-name", package.name) + .property("package-arch", package.arch) + .property("package-installed-version", package.installed_version) + .property("package-candidate-version", package.candidate_version) + .build() + } +} +// ANCHOR_END: mod + +impl Default for AptPackageRow { + fn default() -> Self { + Self::new(AptPackageSocket{ + name: "name".to_string(), + arch: "arch".to_string(), + installed_version: "0.0".to_string(), + candidate_version: "0.0".to_string() + }) + } +} \ No newline at end of file diff --git a/src/gui/apt_update_page/mod.rs b/src/gui/apt_update_page/mod.rs index 2d1edaa..ce5dd62 100644 --- a/src/gui/apt_update_page/mod.rs +++ b/src/gui/apt_update_page/mod.rs @@ -4,25 +4,29 @@ use rust_apt::*; use rust_apt::cache::*; use rust_apt::new_cache; use std::process::Command; -use gtk::glib::prelude::*; -use gtk::glib::{clone, MainContext}; -use gtk::prelude::*; +use gtk::glib::*; use adw::prelude::*; use gtk::*; -use adw::*; -use gtk::Orientation::Vertical; use tokio::net::{UnixListener, UnixStream}; use tokio::io::AsyncReadExt; use tokio::runtime::Runtime; use tokio::task; use pika_unixsocket_tools::*; +use crate::apt_package_row::AptPackageRow; -pub fn apt_update_page(window: &adw::ApplicationWindow) -> gtk::Box { +pub struct AptPackageSocket { + pub name: String, + pub arch: String, + pub installed_version: String, + pub candidate_version: String +} + +pub fn apt_update_page(window: adw::ApplicationWindow) -> gtk::Box { let (update_percent_sender, update_percent_receiver) = async_channel::unbounded::(); let update_percent_sender = update_percent_sender.clone(); let (update_status_sender, update_status_receiver) = async_channel::unbounded::(); let update_status_sender = update_status_sender.clone(); - let (get_upgradable_sender, get_upgradable_receiver) = async_channel::unbounded::(); + let (get_upgradable_sender, get_upgradable_receiver) = async_channel::unbounded(); let get_upgradable_sender = get_upgradable_sender.clone(); thread::spawn(move || { @@ -33,16 +37,56 @@ pub fn apt_update_page(window: &adw::ApplicationWindow) -> gtk::Box { Runtime::new().unwrap().block_on(update_status_socket_server(update_status_sender)); }); - thread::spawn(move || { - Runtime::new().unwrap().block_on(get_upgradable_socket_server(get_upgradable_sender)); - }); - Command::new("pkexec") .args(["/home/ward/RustroverProjects/project-leoali/target/debug/apt_update"]) .spawn(); + let main_box = gtk::Box::builder() + .hexpand(true) + .vexpand(true) + .orientation(Orientation::Vertical) + .build(); + + let searchbar = gtk::SearchEntry::builder() + .search_delay(500) + .margin_bottom(15) + .margin_start(15) + .margin_end(30) + .margin_start(30) + .build(); + searchbar.add_css_class("rounded-all-25"); + + let packages_boxedlist = gtk::ListBox::builder() + .selection_mode(SelectionMode::None) + .margin_bottom(15) + .margin_start(15) + .margin_end(15) + .margin_start(15) + .build(); + packages_boxedlist.add_css_class("boxed-list"); + let rows_size_group = gtk::SizeGroup::new(SizeGroupMode::Both); + + packages_boxedlist.append(&AptPackageRow::new(AptPackageSocket{ + name: "name".to_string(), + arch: "arch".to_string(), + installed_version: "0.0".to_string(), + candidate_version: "0.0".to_string() + })); + + let packages_viewport = gtk::ScrolledWindow::builder() + .hscrollbar_policy(PolicyType::Never) + .vexpand(true) + .hexpand(true) + .margin_bottom(15) + .margin_start(15) + .margin_end(15) + .margin_start(15) + .height_request(390) + .child(&packages_boxedlist) + .build(); + let apt_update_dialog_child_box = gtk::Box::builder() - .orientation(Vertical) + .orientation(Orientation::Vertical) .build(); let apt_update_dialog_progress_bar = gtk::ProgressBar::builder() @@ -61,7 +105,7 @@ pub fn apt_update_page(window: &adw::ApplicationWindow) -> gtk::Box { apt_update_dialog_child_box.append(&apt_update_dialog_progress_bar); let apt_update_dialog = adw::MessageDialog::builder() - .transient_for(window) + .transient_for(&window) .extra_child(&apt_update_dialog_child_box) .heading(t!("apt_update_dialog_heading")) .hide_on_close(true) @@ -70,11 +114,29 @@ pub fn apt_update_page(window: &adw::ApplicationWindow) -> gtk::Box { let update_percent_server_context = MainContext::default(); // The main loop executes the asynchronous block - update_percent_server_context.spawn_local(clone!(@weak apt_update_dialog_progress_bar, @weak apt_update_dialog => async move { + update_percent_server_context.spawn_local(clone!(@weak apt_update_dialog_progress_bar, @weak apt_update_dialog, @strong get_upgradable_sender => async move { while let Ok(state) = update_percent_receiver.recv().await { match state.as_ref() { "FN_OVERRIDE_SUCCESSFUL" => { - apt_update_dialog.close() + let get_upgradable_sender = get_upgradable_sender.clone(); + thread::spawn( move || { + // Create upgradable list cache + let upgradable_cache = new_cache!().unwrap(); + + // Create pack sort from upgradable_cache + let upgradable_sort = PackageSort::default().upgradable().names(); + + for pkg in upgradable_cache.packages(&upgradable_sort) { + let package_struct = AptPackageSocket { + name: pkg.name().to_string(), + arch: pkg.arch().to_string(), + installed_version: pkg.installed().unwrap().version().to_string(), + candidate_version: pkg.candidate().unwrap().version().to_string() + }; + get_upgradable_sender.send_blocking(package_struct).unwrap() + } + }); + apt_update_dialog.close(); } _ => { apt_update_dialog_progress_bar.set_fraction(state.parse::().unwrap()/100.0) @@ -98,13 +160,16 @@ pub fn apt_update_page(window: &adw::ApplicationWindow) -> gtk::Box { // The main loop executes the asynchronous block get_upgradable_server_context.spawn_local(clone!(@weak window => async move { while let Ok(state) = get_upgradable_receiver.recv().await { - println!("{}", state) + println!("{}", state.name) } })); + main_box.append(&searchbar); + main_box.append(&packages_viewport); + apt_update_dialog.present(); - gtk::Box::new(Vertical, 0) + main_box } diff --git a/src/gui/build_ui/mod.rs b/src/gui/build_ui/mod.rs index 8c15a3e..99a6faa 100644 --- a/src/gui/build_ui/mod.rs +++ b/src/gui/build_ui/mod.rs @@ -1,16 +1,72 @@ use adw::prelude::*; use adw::*; -use gtk::Orientation; +use gtk::{Orientation, License}; use crate::apt_update_page; use crate::apt_update_page::apt_update_page; -use crate::config::{APP_ICON, APP_ID}; +use crate::config::{APP_ICON, APP_ID, APP_GITHUB, VERSION}; +use gtk::glib::{clone, MainContext}; +use std::thread; +use std::process::Command; +use std::cell::RefCell; +use std::rc::Rc; pub fn build_ui(app: &adw::Application) { // setup glib gtk::glib::set_prgname(Some(t!("app_name").to_string())); glib::set_application_name(&t!("app_name").to_string()); - let window_child = gtk::Box::new(Orientation::Vertical, 0); + let internet_connected = Rc::new(RefCell::new(false)); + let (internet_loop_sender, internet_loop_receiver) = async_channel::unbounded(); + let internet_loop_sender = internet_loop_sender.clone(); + + std::thread::spawn(move || loop { + match Command::new("ping").arg("google.com").arg("-c 1").output() { + Ok(t) if t.status.success() => internet_loop_sender + .send_blocking(true) + .expect("The channel needs to be open"), + _ => internet_loop_sender + .send_blocking(false) + .expect("The channel needs to be open"), + }; + thread::sleep(std::time::Duration::from_secs(5)); + }); + + let window_banner = adw::Banner::builder().revealed(false).build(); + + 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 window_banner => async move { + while let Ok(state) = internet_loop_receiver.recv().await { + let banner_text = t!("banner_text_no_internet").to_string(); + if state == true { + *internet_connected_status.borrow_mut()=true; + if window_banner.title() == banner_text { + window_banner.set_revealed(false) + } + } else { + *internet_connected_status.borrow_mut()=false; + if window_banner.title() != t!("banner_text_url_error").to_string() { + window_banner.set_title(&banner_text); + window_banner.set_revealed(true) + } + } + } + })); + + let window_headerbar = adw::HeaderBar::builder() + .title_widget( + &adw::WindowTitle::builder() + .title(t!("application_name")) + .build(), + ) + .build(); + + let window_toolbar = adw::ToolbarView::builder().build(); + + window_toolbar.add_top_bar(&window_headerbar); + window_toolbar.add_top_bar(&window_banner); // create the main Application window let window = adw::ApplicationWindow::builder() @@ -24,15 +80,33 @@ pub fn build_ui(app: &adw::Application) { // Minimum Size/Default .width_request(700) .height_request(500) - .content(&window_child) - .deletable(false) + .content(&window_toolbar) // Startup .startup_id(APP_ID) // build the window .build(); - window_child.append(&apt_update_page::apt_update_page(&window)); + let credits_button = gtk::Button::builder() + .icon_name("dialog-information-symbolic") + .build(); + + let credits_window = adw::AboutWindow::builder() + .application_icon(APP_ICON) + .application_name(t!("application_name")) + .transient_for(&window) + .version(VERSION) + .hide_on_close(true) + .developer_name(t!("developer_name")) + .license_type(License::Gpl20) + .issue_url(APP_GITHUB.to_owned() + "/issues") + .build(); + + window_headerbar.pack_end(&credits_button); + credits_button + .connect_clicked(clone!(@weak credits_button => move |_| credits_window.present())); // show the window - window.present() + window.present(); + + window_toolbar.set_content(Some(&apt_update_page::apt_update_page(window))); } \ No newline at end of file diff --git a/src/gui/config.rs b/src/gui/config.rs index 5e9b3ea..3b8b8f4 100644 --- a/src/gui/config.rs +++ b/src/gui/config.rs @@ -1,5 +1,5 @@ pub const APP_ID: &str = "com.github.pikaos-linux.pikafirstsetup"; pub const DISTRO_ICON: &str = "pika-logo"; -//pub const VERSION: &str = env!("CARGO_PKG_VERSION"); +pub const VERSION: &str = env!("CARGO_PKG_VERSION"); pub const APP_ICON: &str = "com.github.pikaos-linux.pikawelcome"; -//pub const APP_GITHUB: &str = "https://github.com/PikaOS-Linux/pkg-pika-welcome"; \ No newline at end of file +pub const APP_GITHUB: &str = "https://github.com/PikaOS-Linux/pkg-pika-welcome"; \ No newline at end of file diff --git a/src/gui/main.rs b/src/gui/main.rs index 3c7f4f9..ed19d36 100644 --- a/src/gui/main.rs +++ b/src/gui/main.rs @@ -2,6 +2,7 @@ mod config; mod build_ui; mod apt_update_page; +mod apt_package_row; use std::env; use adw::prelude::*; diff --git a/src/gui/style.css b/src/gui/style.css index e69de29..1096c28 100644 --- a/src/gui/style.css +++ b/src/gui/style.css @@ -0,0 +1,51 @@ +.symbolic-accent-bg { + color: @accent_bg_color; +} + +.size-20-font { + font-size: 20px; +} + +.rounded-all-25 { + border-radius: 25px; +} + +.background-accent-bg { + background: @accent_bg_color; + border-radius: 10px; + padding: 5px; +} + +.background-green-bg { + background: green; + border-radius: 10px; + padding: 5px; +} + +.background-red-bg { + background: #ff2a03; + border-radius: 10px; + padding: 5px; +} + +.round-border-only-top { + border-top-right-radius: 15px; + border-top-left-radius: 15px; + border-bottom-right-radius: 0px; + border-bottom-left-radius: 0px; +} + +.round-border-only-bottom { + border-top-right-radius: 0px; + border-top-left-radius: 0px; + border-bottom-right-radius: 15px; + border-bottom-left-radius: 15px; +} + +.destructive-color-text { + color: @destructive_bg_color; +} + +.success-color-text { + color: @success_bg_color; +} \ No newline at end of file