From 3b7b69665b56b762808651cb055ea7faa24ea5e9 Mon Sep 17 00:00:00 2001 From: Ward from fusion-voyager-3 Date: Wed, 26 Jun 2024 14:31:55 +0300 Subject: [PATCH] integrate client cli with server ui --- Cargo.lock | 160 +++----------- Cargo.toml | 17 +- src/apt_get_upgradable/main.rs | 55 +++++ src/apt_update/main.rs | 101 ++------- src/debug_server/get_upgradable.rs | 55 +++++ src/debug_server/update_percent.rs | 55 +++++ .../{main.rs => update_status.rs} | 2 +- src/gui/apt_update_page/mod.rs | 200 +++++++++++++++++- src/gui/build_ui/mod.rs | 6 +- src/pika_unixsocket_tools/lib.rs | 40 ++++ 10 files changed, 469 insertions(+), 222 deletions(-) create mode 100644 src/debug_server/get_upgradable.rs create mode 100644 src/debug_server/update_percent.rs rename src/debug_server/{main.rs => update_status.rs} (95%) create mode 100644 src/pika_unixsocket_tools/lib.rs diff --git a/Cargo.lock b/Cargo.lock index e946774..29b11c6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -134,7 +134,7 @@ checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" dependencies = [ "bitflags 2.5.0", "cairo-sys-rs", - "glib 0.18.5", + "glib", "libc", "once_cell", "thiserror", @@ -146,7 +146,7 @@ version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51" dependencies = [ - "glib-sys 0.18.1", + "glib-sys", "libc", "system-deps", ] @@ -459,7 +459,7 @@ checksum = "50e1f5f1b0bfb830d6ccc8066d18db35c487b1b2b1e8589b5dfe9f07e8defaec" dependencies = [ "gdk-pixbuf-sys", "gio", - "glib 0.18.5", + "glib", "libc", "once_cell", ] @@ -470,9 +470,9 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9839ea644ed9c97a34d129ad56d38a25e6756f99f3a88e15cd39c20629caf7" dependencies = [ - "gio-sys 0.18.1", - "glib-sys 0.18.1", - "gobject-sys 0.18.0", + "gio-sys", + "glib-sys", + "gobject-sys", "libc", "system-deps", ] @@ -487,7 +487,7 @@ dependencies = [ "gdk-pixbuf", "gdk4-sys", "gio", - "glib 0.18.5", + "glib", "libc", "pango", ] @@ -500,9 +500,9 @@ checksum = "dbab43f332a3cf1df9974da690b5bb0e26720ed09a228178ce52175372dcfef0" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", - "gio-sys 0.18.1", - "glib-sys 0.18.1", - "gobject-sys 0.18.0", + "gio-sys", + "glib-sys", + "gobject-sys", "libc", "pango-sys", "pkg-config", @@ -525,8 +525,8 @@ dependencies = [ "futures-core", "futures-io", "futures-util", - "gio-sys 0.18.1", - "glib 0.18.5", + "gio-sys", + "glib", "libc", "once_cell", "pin-project-lite", @@ -540,26 +540,13 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2" dependencies = [ - "glib-sys 0.18.1", - "gobject-sys 0.18.0", + "glib-sys", + "gobject-sys", "libc", "system-deps", "winapi 0.3.9", ] -[[package]] -name = "gio-sys" -version = "0.19.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cd743ba4714d671ad6b6234e8ab2a13b42304d0e13ab7eba1dcdd78a7d6d4ef" -dependencies = [ - "glib-sys 0.19.8", - "gobject-sys 0.19.8", - "libc", - "system-deps", - "windows-sys 0.52.0", -] - [[package]] name = "glib" version = "0.18.5" @@ -572,10 +559,10 @@ dependencies = [ "futures-executor", "futures-task", "futures-util", - "gio-sys 0.18.1", - "glib-macros 0.18.5", - "glib-sys 0.18.1", - "gobject-sys 0.18.0", + "gio-sys", + "glib-macros", + "glib-sys", + "gobject-sys", "libc", "memchr", "once_cell", @@ -583,28 +570,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "glib" -version = "0.19.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b664491bc77ab55daa6714a592cdbe1a55e28abec09cb50e87689b90de456ff4" -dependencies = [ - "bitflags 2.5.0", - "futures-channel", - "futures-core", - "futures-executor", - "futures-task", - "futures-util", - "gio-sys 0.19.8", - "glib-macros 0.19.8", - "glib-sys 0.19.8", - "gobject-sys 0.19.8", - "libc", - "memchr", - "smallvec 1.13.2", - "thiserror", -] - [[package]] name = "glib-macros" version = "0.18.5" @@ -619,19 +584,6 @@ dependencies = [ "syn 2.0.68", ] -[[package]] -name = "glib-macros" -version = "0.19.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d405205a405182f95e637710850a8e82f25ba01fdd6baebc82dabeaf0883376" -dependencies = [ - "heck 0.5.0", - "proc-macro-crate 3.1.0", - "proc-macro2", - "quote", - "syn 2.0.68", -] - [[package]] name = "glib-sys" version = "0.18.1" @@ -642,16 +594,6 @@ dependencies = [ "system-deps", ] -[[package]] -name = "glib-sys" -version = "0.19.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c2dc18d3a82b0006d470b13304fbbb3e0a9bd4884cf985a60a7ed733ac2c4a5" -dependencies = [ - "libc", - "system-deps", -] - [[package]] name = "glob" version = "0.3.1" @@ -688,18 +630,7 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44" dependencies = [ - "glib-sys 0.18.1", - "libc", - "system-deps", -] - -[[package]] -name = "gobject-sys" -version = "0.19.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e697e252d6e0416fd1d9e169bda51c0f1c926026c39ca21fbe8b1bb5c3b8b9e" -dependencies = [ - "glib-sys 0.19.8", + "glib-sys", "libc", "system-deps", ] @@ -710,7 +641,7 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b2228cda1505613a7a956cca69076892cfbda84fc2b7a62b94a41a272c0c401" dependencies = [ - "glib 0.18.5", + "glib", "graphene-sys", "libc", ] @@ -721,7 +652,7 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc4144cee8fc8788f2a9b73dc5f1d4e1189d1f95305c4cb7bd9c1af1cfa31f59" dependencies = [ - "glib-sys 0.18.1", + "glib-sys", "libc", "pkg-config", "system-deps", @@ -735,7 +666,7 @@ checksum = "0d958e351d2f210309b32d081c832d7de0aca0b077aa10d88336c6379bd01f7e" dependencies = [ "cairo-rs", "gdk4", - "glib 0.18.5", + "glib", "graphene-rs", "gsk4-sys", "libc", @@ -750,8 +681,8 @@ checksum = "12bd9e3effea989f020e8f1ff3fa3b8c63ba93d43b899c11a118868853a56d55" dependencies = [ "cairo-sys-rs", "gdk4-sys", - "glib-sys 0.18.1", - "gobject-sys 0.18.0", + "glib-sys", + "gobject-sys", "graphene-sys", "libc", "pango-sys", @@ -770,7 +701,7 @@ dependencies = [ "gdk-pixbuf", "gdk4", "gio", - "glib 0.18.5", + "glib", "graphene-rs", "gsk4", "gtk4-macros", @@ -802,9 +733,9 @@ dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", "gdk4-sys", - "gio-sys 0.18.1", - "glib-sys 0.18.1", - "gobject-sys 0.18.0", + "gio-sys", + "glib-sys", + "gobject-sys", "graphene-sys", "gsk4-sys", "libc", @@ -918,7 +849,7 @@ dependencies = [ "gdk-pixbuf", "gdk4", "gio", - "glib 0.18.5", + "glib", "gtk4", "libadwaita-sys", "libc", @@ -932,9 +863,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e10aaa38de1d53374f90deeb4535209adc40cc5dba37f9704724169bceec69a" dependencies = [ "gdk4-sys", - "gio-sys 0.18.1", - "glib-sys 0.18.1", - "gobject-sys 0.18.0", + "gio-sys", + "glib-sys", + "gobject-sys", "gtk4-sys", "libc", "pango-sys", @@ -1128,7 +1059,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4" dependencies = [ "gio", - "glib 0.18.5", + "glib", "libc", "once_cell", "pango-sys", @@ -1140,8 +1071,8 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "436737e391a843e5933d6d9aa102cb126d501e815b83601365a948a518555dc5" dependencies = [ - "glib-sys 0.18.1", - "gobject-sys 0.18.0", + "glib-sys", + "gobject-sys", "libc", "system-deps", ] @@ -1244,15 +1175,6 @@ dependencies = [ "toml_edit 0.20.2", ] -[[package]] -name = "proc-macro-crate" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" -dependencies = [ - "toml_edit 0.21.1", -] - [[package]] name = "proc-macro-error" version = "1.0.4" @@ -1293,7 +1215,6 @@ dependencies = [ "async-channel", "async-trait", "futures 0.3.30", - "glib 0.19.8", "gtk4", "libadwaita", "rust-apt", @@ -1853,17 +1774,6 @@ dependencies = [ "winnow", ] -[[package]] -name = "toml_edit" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" -dependencies = [ - "indexmap 2.2.6", - "toml_datetime", - "winnow", -] - [[package]] name = "triomphe" version = "0.1.13" diff --git a/Cargo.toml b/Cargo.toml index ecbef3d..6ee1c40 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,14 +8,26 @@ edition = "2021" name = "gui" path = "src/gui/main.rs" +[lib] +name = "pika_unixsocket_tools" +path = "src/pika_unixsocket_tools/lib.rs" + [[bin]] -name = "debug_server" -path = "src/debug_server/main.rs" +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"] } @@ -28,4 +40,3 @@ serde = { version = "1.0.203", features = ["derive"] } serde_json = "1.0.118" async-trait = "0.1.80" futures = "0.3.30" -glib = "0.19.8" diff --git a/src/apt_get_upgradable/main.rs b/src/apt_get_upgradable/main.rs index e69de29..ec064cf 100644 --- a/src/apt_get_upgradable/main.rs +++ b/src/apt_get_upgradable/main.rs @@ -0,0 +1,55 @@ +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/apt_update/main.rs b/src/apt_update/main.rs index 7f0ed33..f590d9f 100644 --- a/src/apt_update/main.rs +++ b/src/apt_update/main.rs @@ -1,19 +1,11 @@ use rust_apt::new_cache; -use rust_apt::cache::*; use tokio::net::{UnixStream}; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use rust_apt::progress::{AcquireProgress, DynAcquireProgress}; use rust_apt::raw::{AcqTextStatus, ItemDesc, PkgAcquire}; use tokio::runtime::Runtime; +use pika_unixsocket_tools::*; -use serde::{Serialize, Deserialize}; -#[derive(Serialize)] -struct AptSendablePackage { - name: String, - arch: String, - installed_version: String, - candidate_version: String -} pub struct AptUpdateProgressSocket<'a> { pulse_interval: usize, max: usize, @@ -63,7 +55,7 @@ impl<'a> DynAcquireProgress for AptUpdateProgressSocket<'a> { /// /// Prints out the short description and the expected size. fn fetch(&mut self, item: &ItemDesc) { - let message = format!("Downloading: {} {}", item.description(), item.short_desc()); + let message = format!("Fetching: {} {}", item.description(), item.short_desc()); println!("{}", message); Runtime::new().unwrap().block_on(send_progress_status(message, self.status_socket_path)); } @@ -72,7 +64,7 @@ impl<'a> DynAcquireProgress for AptUpdateProgressSocket<'a> { /// /// We don't print anything here to remain consistent with apt. fn done(&mut self, item: &ItemDesc) { - let message = format!("Download Successful: {} {}", item.description(), item.short_desc()); + let message = format!("Downloading: {} {}", item.description(), item.short_desc()); println!("{}", message); Runtime::new().unwrap().block_on(send_progress_status(message, self.status_socket_path)); } @@ -113,9 +105,18 @@ impl<'a> DynAcquireProgress for AptUpdateProgressSocket<'a> { fn main() { let update_cache = new_cache!().unwrap(); - match update_cache.update(&mut AcquireProgress::new(AptUpdateProgressSocket::new("/tmp/pika_apt_update.sock", "/tmp/pika_apt_update.sock"))) { - Ok(_) => {} - Err(e) => panic!("{}", e.to_string()) + let percent_socket_path = "/tmp/pika_apt_update_percent.sock"; + let status_socket_path = "/tmp/pika_apt_update_status.sock"; + match update_cache.update(&mut AcquireProgress::new(AptUpdateProgressSocket::new(percent_socket_path, status_socket_path))) { + Ok(_) => { + Runtime::new().unwrap().block_on(send_successful_to_socket(percent_socket_path)); + Runtime::new().unwrap().block_on(send_successful_to_socket(status_socket_path)); + } + Err(e) => { + Runtime::new().unwrap().block_on(send_failed_to_socket(percent_socket_path)); + Runtime::new().unwrap().block_on(send_failed_to_socket(status_socket_path)); + panic!("{}", e.to_string()) + } }; } @@ -126,21 +127,6 @@ async fn send_progress_percent(progress_f32: f32, socket_path: &str) { let message = progress_f32.to_string(); // 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); - } - } } async fn send_progress_status(message: String, socket_path: &str) { @@ -149,61 +135,4 @@ async fn send_progress_status(message: String, socket_path: &str) { // 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); - } - } -} - -async fn get_upgradable_packages() { - // 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 = AptSendablePackage { - 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_update.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 new file mode 100644 index 0000000..5f9ee9e --- /dev/null +++ b/src/debug_server/get_upgradable.rs @@ -0,0 +1,55 @@ +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 new file mode 100644 index 0000000..cc41185 --- /dev/null +++ b/src/debug_server/update_percent.rs @@ -0,0 +1,55 @@ +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/main.rs b/src/debug_server/update_status.rs similarity index 95% rename from src/debug_server/main.rs rename to src/debug_server/update_status.rs index 6aff358..d80432b 100644 --- a/src/debug_server/main.rs +++ b/src/debug_server/update_status.rs @@ -8,7 +8,7 @@ use std::fs; #[tokio::main] async fn main() { // Path to the Unix socket file - let pika_apt_update_socket_path = "/tmp/pika_apt_update.sock"; + 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() { diff --git a/src/gui/apt_update_page/mod.rs b/src/gui/apt_update_page/mod.rs index 318a4ee..2d1edaa 100644 --- a/src/gui/apt_update_page/mod.rs +++ b/src/gui/apt_update_page/mod.rs @@ -1,10 +1,198 @@ +use std::{fs, thread}; +use std::path::Path; use rust_apt::*; use rust_apt::cache::*; use rust_apt::new_cache; -pub fn apt_update_page() { - let cache = match new_cache!() { - Ok(t) => t, - Err(_) => panic!("APT CACHE FAIL") - }; - let sort = PackageSort::default().upgradable().names(); +use std::process::Command; +use gtk::glib::prelude::*; +use gtk::glib::{clone, MainContext}; +use gtk::prelude::*; +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::*; + +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_sender.clone(); + + thread::spawn(move || { + Runtime::new().unwrap().block_on(update_percent_socket_server(update_percent_sender)); + }); + + thread::spawn(move || { + 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 apt_update_dialog_child_box = gtk::Box::builder() + .orientation(Vertical) + .build(); + + let apt_update_dialog_progress_bar = gtk::ProgressBar::builder() + .show_text(true) + .hexpand(true) + .build(); + + apt_update_dialog_child_box.append(>k::Spinner::builder() + .hexpand(true) + .valign(Align::Start) + .halign(Align::Center) + .spinning(true) + .height_request(128) + .width_request(128) + .build()); + apt_update_dialog_child_box.append(&apt_update_dialog_progress_bar); + + let apt_update_dialog = adw::MessageDialog::builder() + .transient_for(window) + .extra_child(&apt_update_dialog_child_box) + .heading(t!("apt_update_dialog_heading")) + .hide_on_close(true) + .width_request(500) + .build(); + + 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 { + while let Ok(state) = update_percent_receiver.recv().await { + match state.as_ref() { + "FN_OVERRIDE_SUCCESSFUL" => { + apt_update_dialog.close() + } + _ => { + apt_update_dialog_progress_bar.set_fraction(state.parse::().unwrap()/100.0) + } + } + } + })); + + let update_status_server_context = MainContext::default(); + // The main loop executes the asynchronous block + update_status_server_context.spawn_local(clone!(@weak apt_update_dialog => async move { + while let Ok(state) = update_status_receiver.recv().await { + match state.as_ref() { + "FN_OVERRIDE_SUCCESSFUL" => {} + _ => apt_update_dialog.set_body(&state) + } + } + })); + + let get_upgradable_server_context = MainContext::default(); + // 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) + } + })); + + + apt_update_dialog.present(); + gtk::Box::new(Vertical, 0) +} + + +async fn update_percent_socket_server(buffer_sender: async_channel::Sender) { + // Path to the Unix socket file + let socket_path = "/tmp/pika_apt_update_percent.sock"; + + // Remove the socket file if it already exists + if Path::new(socket_path).exists() { + fs::remove_file(socket_path).expect("Could not remove existing socket file"); + } + + // Bind the Unix listener to the socket path + let listener = UnixListener::bind(socket_path).expect("Could not bind"); + + println!("Server listening on {}", socket_path); + + // Loop to accept incoming connections + loop { + // Accept an incoming connection + match listener.accept().await { + Ok((stream, _)) => { + // Handle the connection in a separate task + task::spawn(handle_client(stream, buffer_sender.clone())); + } + Err(e) => { + // Print error message if a connection fails + eprintln!("Connection failed: {}", e); + } + } + } +} + +async fn update_status_socket_server(buffer_sender: async_channel::Sender) { + // Path to the Unix socket file + let socket_path = "/tmp/pika_apt_update_status.sock"; + + // Remove the socket file if it already exists + if Path::new(socket_path).exists() { + fs::remove_file(socket_path).expect("Could not remove existing socket file"); + } + + // Bind the Unix listener to the socket path + let listener = UnixListener::bind(socket_path).expect("Could not bind"); + + println!("Server listening on {}", socket_path); + + // Loop to accept incoming connections + loop { + // Accept an incoming connection + match listener.accept().await { + Ok((stream, _)) => { + // Handle the connection in a separate task + task::spawn(handle_client(stream, buffer_sender.clone())); + } + Err(e) => { + // Print error message if a connection fails + eprintln!("Connection failed: {}", e); + } + } + } +} +async fn get_upgradable_socket_server(buffer_sender: async_channel::Sender) { + // Path to the Unix socket file + let socket_path = "/tmp/pika_apt_get_upgradable.sock"; + + // Remove the socket file if it already exists + if Path::new(socket_path).exists() { + fs::remove_file(socket_path).expect("Could not remove existing socket file"); + } + + // Bind the Unix listener to the socket path + let listener = UnixListener::bind(socket_path).expect("Could not bind"); + + println!("Server listening on {}", socket_path); + + // Loop to accept incoming connections + loop { + // Accept an incoming connection + match listener.accept().await { + Ok((stream, _)) => { + // Handle the connection in a separate task + task::spawn(handle_client(stream, buffer_sender.clone())); + } + Err(e) => { + // Print error message if a connection fails + eprintln!("Connection failed: {}", e); + } + } + } } \ No newline at end of file diff --git a/src/gui/build_ui/mod.rs b/src/gui/build_ui/mod.rs index 05989aa..8c15a3e 100644 --- a/src/gui/build_ui/mod.rs +++ b/src/gui/build_ui/mod.rs @@ -1,5 +1,6 @@ use adw::prelude::*; use adw::*; +use gtk::Orientation; use crate::apt_update_page; use crate::apt_update_page::apt_update_page; use crate::config::{APP_ICON, APP_ID}; @@ -9,6 +10,8 @@ pub fn build_ui(app: &adw::Application) { 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); + // create the main Application window let window = adw::ApplicationWindow::builder() // The text on the titlebar @@ -21,13 +24,14 @@ pub fn build_ui(app: &adw::Application) { // Minimum Size/Default .width_request(700) .height_request(500) + .content(&window_child) .deletable(false) // Startup .startup_id(APP_ID) // build the window .build(); - apt_update_page::apt_update_page(); + window_child.append(&apt_update_page::apt_update_page(&window)); // show the window window.present() diff --git a/src/pika_unixsocket_tools/lib.rs b/src/pika_unixsocket_tools/lib.rs new file mode 100644 index 0000000..32b438a --- /dev/null +++ b/src/pika_unixsocket_tools/lib.rs @@ -0,0 +1,40 @@ +use tokio::net::{UnixStream}; +use tokio::io::{AsyncReadExt, AsyncWriteExt}; + +pub async fn send_successful_to_socket(socket_path: &str) { + // Connect to the Unix socket + let mut stream = UnixStream::connect(socket_path).await.expect("Could not connect to server"); + + let message = "FN_OVERRIDE_SUCCESSFUL"; + + // Send the message to the server + stream.write_all(message.as_bytes()).await.expect("Failed to write to stream"); +} + +pub async fn send_failed_to_socket(socket_path: &str) { + // Connect to the Unix socket + let mut stream = UnixStream::connect(socket_path).await.expect("Could not connect to server"); + + let message = "FN_OVERRIDE_FAILED"; + + // Send the message to the server + stream.write_all(message.as_bytes()).await.expect("Failed to write to stream"); +} + +// Function to handle a single client connection +pub async fn handle_client(mut stream: UnixStream, buffer_sender: async_channel::Sender) { + // 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 + buffer_sender.send_blocking(String::from_utf8_lossy(&buffer[..size]).to_string()).expect("Buffer channel closed") + } + Err(e) => { + // Print error message if reading fails + eprintln!("Failed to read from stream: {}", e); + } + } +} \ No newline at end of file