integrate client cli with server ui
This commit is contained in:
parent
3b7b69665b
commit
2e8b590ffd
12
Cargo.toml
12
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"] }
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
173
src/gui/apt_package_row/imp.rs
Normal file
173
src/gui/apt_package_row/imp.rs
Normal file
@ -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<String>,
|
||||
#[property(get, set)]
|
||||
package_arch: RefCell<String>,
|
||||
#[property(get, set)]
|
||||
package_installed_version: RefCell<String>,
|
||||
#[property(get, set)]
|
||||
package_candidate_version: RefCell<String>
|
||||
}
|
||||
// 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<Vec<Signal>> = 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())
|
||||
}
|
34
src/gui/apt_package_row/mod.rs
Normal file
34
src/gui/apt_package_row/mod.rs
Normal file
@ -0,0 +1,34 @@
|
||||
mod imp;
|
||||
|
||||
use glib::Object;
|
||||
use gtk::glib;
|
||||
use crate::apt_update_page::AptPackageSocket;
|
||||
|
||||
glib::wrapper! {
|
||||
pub struct AptPackageRow(ObjectSubclass<imp::AptPackageRow>)
|
||||
@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()
|
||||
})
|
||||
}
|
||||
}
|
@ -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::<String>();
|
||||
let update_percent_sender = update_percent_sender.clone();
|
||||
let (update_status_sender, update_status_receiver) = async_channel::unbounded::<String>();
|
||||
let update_status_sender = update_status_sender.clone();
|
||||
let (get_upgradable_sender, get_upgradable_receiver) = async_channel::unbounded::<String>();
|
||||
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::<f64>().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
|
||||
}
|
||||
|
||||
|
||||
|
@ -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)));
|
||||
}
|
@ -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";
|
||||
pub const APP_GITHUB: &str = "https://github.com/PikaOS-Linux/pkg-pika-welcome";
|
@ -2,6 +2,7 @@
|
||||
mod config;
|
||||
mod build_ui;
|
||||
mod apt_update_page;
|
||||
mod apt_package_row;
|
||||
|
||||
use std::env;
|
||||
use adw::prelude::*;
|
||||
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user