fix luks dialog when errored

This commit is contained in:
Ward from fusion-voyager-3 2024-08-20 23:07:07 +03:00
parent 2f36e404a5
commit b466462550

View File

@ -9,6 +9,8 @@ use glib::{clone, closure_local, ffi::gboolean};
use gtk::glib::Variant; use gtk::glib::Variant;
use gtk::{glib, prelude::*, Orientation}; use gtk::{glib, prelude::*, Orientation};
use std::{cell::RefCell, collections::HashSet, rc::Rc}; use std::{cell::RefCell, collections::HashSet, rc::Rc};
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
mod func; mod func;
@ -108,17 +110,30 @@ pub fn manual_partitioning_page(
let partition_method_manual_mountpoint_empty_error_label = gtk::Label::builder() let partition_method_manual_mountpoint_empty_error_label = gtk::Label::builder()
.halign(gtk::Align::Start) .halign(gtk::Align::Start)
.valign(gtk::Align::End) .valign(gtk::Align::End)
.visible(false)
.build(); .build();
partition_method_manual_mountpoint_empty_error_label.add_css_class("small_error_text");
let partition_method_manual_mountpoint_invalid_error_label = gtk::Label::builder() let partition_method_manual_mountpoint_invalid_error_label = gtk::Label::builder()
.halign(gtk::Align::Start) .halign(gtk::Align::Start)
.valign(gtk::Align::End) .valign(gtk::Align::End)
.visible(false)
.build(); .build();
partition_method_manual_mountpoint_invalid_error_label.add_css_class("small_error_text");
let partition_method_manual_partition_empty_error_label = gtk::Label::builder() let partition_method_manual_partition_empty_error_label = gtk::Label::builder()
.halign(gtk::Align::Start) .halign(gtk::Align::Start)
.valign(gtk::Align::End) .valign(gtk::Align::End)
.visible(false)
.build(); .build();
partition_method_manual_partition_empty_error_label.add_css_class("small_error_text");
let partition_method_manual_mountpoint_duplicate_label = gtk::Label::builder()
.halign(gtk::Align::Start)
.valign(gtk::Align::End)
.visible(false)
.build();
partition_method_manual_mountpoint_duplicate_label.add_css_class("small_error_text");
utility_buttons_box.append(&open_disk_utility_button); utility_buttons_box.append(&open_disk_utility_button);
utility_buttons_box.append(&filesystem_table_refresh_button); utility_buttons_box.append(&filesystem_table_refresh_button);
@ -197,161 +212,105 @@ pub fn manual_partitioning_page(
partition_method_manual_crypttab_entry_array_refcell, partition_method_manual_crypttab_entry_array_refcell,
#[strong] #[strong]
subvol_partition_array_refcell, subvol_partition_array_refcell,
#[weak]
partition_method_manual_mountpoint_empty_error_label,
#[weak]
partition_method_manual_mountpoint_invalid_error_label,
#[weak]
partition_method_manual_partition_empty_error_label,
#[weak]
partition_method_manual_mountpoint_duplicate_label,
move |_| { move |_| {
let mut errored = false; let errored = Arc::new(AtomicBool::new(false));
(*partition_method_manual_fstab_entry_array_refcell.borrow_mut()) = Vec::new(); (*partition_method_manual_fstab_entry_array_refcell.borrow_mut()) = Vec::new();
(*partition_method_manual_luks_enabled_refcell.borrow_mut()) = false; (*partition_method_manual_luks_enabled_refcell.borrow_mut()) = false;
(*partition_method_manual_crypttab_entry_array_refcell.borrow_mut()) = Vec::new(); (*partition_method_manual_crypttab_entry_array_refcell.borrow_mut()) = Vec::new();
let mut seen_mountpoints = HashSet::new(); let mut seen_mountpoints = HashSet::new();
let mut seen_partitions = HashSet::new(); let mut seen_partitions = HashSet::new();
let mut seen_crypts = HashSet::new(); let mut seen_crypts: Rc<RefCell<HashSet<String>>> = Rc::new(RefCell::new(HashSet::new()));
partition_method_manual_mountpoint_empty_error_label.set_visible(false);
partition_method_manual_mountpoint_invalid_error_label.set_visible(false);
partition_method_manual_partition_empty_error_label.set_visible(false);
partition_method_manual_mountpoint_duplicate_label.set_visible(false);
for fs_entry in generate_filesystem_table_array(&drive_mounts_adw_listbox) { for fs_entry in generate_filesystem_table_array(&drive_mounts_adw_listbox) {
let fs_entry_clone0 = fs_entry.clone(); let fs_entry_clone0 = fs_entry.clone();
if subvol_partition_array_refcell.borrow().is_empty() { if subvol_partition_array_refcell.borrow().is_empty() {
if !seen_partitions.insert(fs_entry.clone().partition.part_name) { if !seen_partitions.insert(fs_entry.clone().partition.part_name) {
errored = true; (errored.store(true, std::sync::atomic::Ordering::Relaxed));
filesystem_table_refresh_button.emit_by_name_with_values("clicked", &[]); filesystem_table_refresh_button.emit_by_name_with_values("clicked", &[]);
break;
} }
} }
if fs_entry.mountpoint == "[SWAP]" && fs_entry.partition.part_fs != "linux-swap" { if fs_entry.mountpoint == "[SWAP]" && fs_entry.partition.part_fs != "linux-swap" {
errored = true; (errored.store(true, std::sync::atomic::Ordering::Relaxed));
filesystem_table_refresh_button.emit_by_name_with_values("clicked", &[]); filesystem_table_refresh_button.emit_by_name_with_values("clicked", &[]);
break;
} }
if fs_entry.mountpoint.is_empty() { if fs_entry.mountpoint.is_empty() {
errored = true; (errored.store(true, std::sync::atomic::Ordering::Relaxed));
println!("mountpoint empty"); partition_method_manual_mountpoint_empty_error_label.set_visible(true);
break;
} }
if fs_entry.mountpoint == "[SWAP]" if fs_entry.mountpoint == "[SWAP]"
|| fs_entry.mountpoint.starts_with("/") || fs_entry.mountpoint.starts_with("/")
&& !fs_entry.mountpoint.starts_with("/dev") && !fs_entry.mountpoint.starts_with("/dev")
{ {
} else { } else {
errored = true; (errored.store(true, std::sync::atomic::Ordering::Relaxed));
println!("mountpoint invalid"); partition_method_manual_mountpoint_invalid_error_label.set_visible(true);
break;
} }
if fs_entry.partition.part_name.is_empty() { if fs_entry.partition.part_name.is_empty() {
errored = true; (errored.store(true, std::sync::atomic::Ordering::Relaxed));
println!("partition empty"); partition_method_manual_partition_empty_error_label.set_visible(true);
break;
} }
if !seen_mountpoints.insert(fs_entry.clone().mountpoint) { if !seen_mountpoints.insert(fs_entry.clone().mountpoint) {
errored = true; (errored.store(true, std::sync::atomic::Ordering::Relaxed));
break; partition_method_manual_mountpoint_duplicate_label.set_visible(true);
} }
// //
(*partition_method_manual_fstab_entry_array_refcell.borrow_mut()).push(fs_entry); (*partition_method_manual_fstab_entry_array_refcell.borrow_mut()).push(fs_entry);
// //
let (check_delay_sender, check_delay_receiver) = async_channel::unbounded();
if fs_entry_clone0.partition.has_encryption let errored_clone0 = Arc::clone(&errored);
&& seen_crypts.insert(fs_entry_clone0.clone().partition.part_name) std::thread::spawn(move || {
{ std::thread::sleep(std::time::Duration::from_millis(100));
let fs_entry = fs_entry_clone0.clone(); check_delay_sender
let (luks_manual_password_sender, luks_manual_password_receiver) = .send_blocking((errored_clone0))
async_channel::unbounded::<bool>(); .expect("The channel needs to be open.");
let crypttab_password_listbox = gtk::ListBox::builder() });
.margin_top(10)
.margin_bottom(10) let check_delay_main_context = glib::MainContext::default();
.margin_start(10) check_delay_main_context.spawn_local(clone!(
.margin_end(10) #[strong]
.build(); window,
crypttab_password_listbox.add_css_class("boxed-list"); #[strong]
let crypttab_password = adw::PasswordEntryRow::builder() partition_method_manual_luks_enabled_refcell,
.title(t!("luks_password_for").to_string() + &fs_entry.partition.part_name) #[strong]
.build(); partition_method_manual_crypttab_entry_array_refcell,
crypttab_password.set_show_apply_button(true); #[strong]
crypttab_password_listbox.append(&crypttab_password); fs_entry_clone0,
let crypttab_dialog = adw::MessageDialog::builder() #[strong]
.transient_for(&window) seen_crypts,
.hide_on_close(true) async move {
.extra_child(&crypttab_password_listbox) while let Ok(state) = check_delay_receiver.recv().await {
.width_request(400) if state.load(std::sync::atomic::Ordering::Relaxed) == false {
.height_request(200) set_crypttab_entries(&fs_entry_clone0, &seen_crypts, window.clone(), &partition_method_manual_crypttab_entry_array_refcell, &partition_method_manual_luks_enabled_refcell);
.heading(
t!("luks_how_should").to_string()
+ &fs_entry.partition.part_name
+ &t!("be_added_crypttab"),
)
.build();
crypttab_dialog
.add_response("crypttab_dialog_boot", &t!("unlock_boot_manually"));
crypttab_dialog.add_response("crypttab_dialog_auto", &t!("unlock_boot_manual"));
crypttab_dialog.set_response_enabled("crypttab_dialog_auto", false);
crypttab_password.connect_apply(clone!(
#[weak]
crypttab_password,
#[strong]
fs_entry,
#[weak]
crypttab_dialog,
move |_| {
let luks_manual_password_sender = luks_manual_password_sender.clone();
let luks_password = crypttab_password.text().to_string();
let fs_entry_clone1 = fs_entry.clone();
std::thread::spawn(move || {
luks_manual_password_sender
.send_blocking(partitioning_page::test_luks_passwd(
&fs_entry_clone1.partition.part_name,
&luks_password,
))
.expect("The channel needs to be open.");
});
}
));
let luks_manual_password_main_context = glib::MainContext::default();
// The main loop executes the asynchronous block
luks_manual_password_main_context.spawn_local(clone!(
#[weak]
crypttab_dialog,
async move {
while let Ok(state) = luks_manual_password_receiver.recv().await {
crypttab_dialog.set_response_enabled("crypttab_dialog_auto", state);
} }
} }
)); }
));
let partition_method_manual_crypttab_entry_array_refcell_clone0 =
partition_method_manual_crypttab_entry_array_refcell.clone();
let partition_method_manual_luks_enabled_refcell_clone0 =
partition_method_manual_luks_enabled_refcell.clone();
crypttab_dialog.choose(None::<&gio::Cancellable>, move |choice| {
let part_name = fs_entry.partition.part_name;
if choice == "crypttab_dialog_auto" {
(*partition_method_manual_crypttab_entry_array_refcell_clone0
.borrow_mut())
.push(CrypttabEntry {
partition: part_name.clone(),
map: part_name.replace("mapper/", ""),
uuid: get_luks_uuid(&part_name),
password: Some(crypttab_password.text().to_string()),
});
} else {
(*partition_method_manual_crypttab_entry_array_refcell_clone0
.borrow_mut())
.push(CrypttabEntry {
partition: part_name.clone(),
map: part_name.replace("mapper/", ""),
uuid: get_luks_uuid(&part_name),
password: None,
});
}
(*partition_method_manual_luks_enabled_refcell_clone0.borrow_mut()) = true;
});
}
} }
} }
)); ));
content_box.append(&drive_mounts_viewport); content_box.append(&drive_mounts_viewport);
content_box.append(&utility_buttons_box); content_box.append(&utility_buttons_box);
content_box.append(&partition_method_manual_mountpoint_empty_error_label);
content_box.append(&partition_method_manual_mountpoint_invalid_error_label);
content_box.append(&partition_method_manual_partition_empty_error_label);
content_box.append(&partition_method_manual_mountpoint_duplicate_label);
// //
manual_partitioning_page.connect_closure( manual_partitioning_page.connect_closure(
@ -402,11 +361,24 @@ pub fn manual_partitioning_page(
language_changed_action.connect_activate(clone!( language_changed_action.connect_activate(clone!(
#[weak] #[weak]
manual_partitioning_page, manual_partitioning_page,
#[weak]
partition_method_manual_mountpoint_empty_error_label,
#[weak]
partition_method_manual_mountpoint_invalid_error_label,
#[weak]
partition_method_manual_partition_empty_error_label,
#[weak]
partition_method_manual_mountpoint_duplicate_label,
move |_, _| { move |_, _| {
manual_partitioning_page.set_page_title(t!("manual_partitioning_page_title")); manual_partitioning_page.set_page_title(t!("manual_partitioning_page_title"));
manual_partitioning_page.set_page_subtitle(t!("manual_partitioning_page_subtitle")); manual_partitioning_page.set_page_subtitle(t!("manual_partitioning_page_subtitle"));
manual_partitioning_page.set_back_tooltip_label(t!("back")); manual_partitioning_page.set_back_tooltip_label(t!("back"));
manual_partitioning_page.set_next_tooltip_label(t!("next")); manual_partitioning_page.set_next_tooltip_label(t!("next"));
//
partition_method_manual_mountpoint_empty_error_label.set_label(&t!("partition_method_manual_mountpoint_empty_error_label_label"));
partition_method_manual_mountpoint_invalid_error_label.set_label(&t!("partition_method_manual_mountpoint_invalid_error_label_label"));
partition_method_manual_partition_empty_error_label.set_label(&t!("partition_method_manual_partition_empty_error_label_label"));
partition_method_manual_mountpoint_duplicate_label.set_label(&t!("partition_method_manual_mountpoint_duplicate_label_label"));
} }
)); ));
// //
@ -520,3 +492,110 @@ fn generate_filesystem_table_array(drive_mounts_adw_listbox: &gtk::ListBox) -> V
} }
fstab_array fstab_array
} }
fn set_crypttab_entries(
fs_entry: &FstabEntry,
seen_crypts: &Rc<RefCell<HashSet<String>>>,
window: adw::ApplicationWindow,
partition_method_manual_crypttab_entry_array_refcell: &Rc<RefCell<Vec<CrypttabEntry>>>,
partition_method_manual_luks_enabled_refcell: &Rc<RefCell<bool>>,
) {
if fs_entry.partition.has_encryption
&& (*seen_crypts.borrow_mut()).insert(fs_entry.clone().partition.part_name)
{
let fs_entry = fs_entry.clone();
let (luks_manual_password_sender, luks_manual_password_receiver) =
async_channel::unbounded::<bool>();
let crypttab_password_listbox = gtk::ListBox::builder()
.margin_top(10)
.margin_bottom(10)
.margin_start(10)
.margin_end(10)
.build();
crypttab_password_listbox.add_css_class("boxed-list");
let crypttab_password = adw::PasswordEntryRow::builder()
.title(t!("luks_password_for").to_string() + &fs_entry.partition.part_name)
.build();
crypttab_password.set_show_apply_button(true);
crypttab_password_listbox.append(&crypttab_password);
let crypttab_dialog = adw::MessageDialog::builder()
.transient_for(&window)
.hide_on_close(true)
.extra_child(&crypttab_password_listbox)
.width_request(400)
.height_request(200)
.heading(
t!("luks_how_should").to_string()
+ &fs_entry.partition.part_name
+ &t!("be_added_crypttab"),
)
.build();
crypttab_dialog
.add_response("crypttab_dialog_boot", &t!("unlock_boot_manually"));
crypttab_dialog.add_response("crypttab_dialog_auto", &t!("unlock_boot_manual"));
crypttab_dialog.set_response_enabled("crypttab_dialog_auto", false);
crypttab_password.connect_apply(clone!(
#[weak]
crypttab_password,
#[strong]
fs_entry,
#[weak]
crypttab_dialog,
move |_| {
let luks_manual_password_sender = luks_manual_password_sender.clone();
let luks_password = crypttab_password.text().to_string();
let fs_entry_clone1 = fs_entry.clone();
std::thread::spawn(move || {
luks_manual_password_sender
.send_blocking(partitioning_page::test_luks_passwd(
&fs_entry_clone1.partition.part_name,
&luks_password,
))
.expect("The channel needs to be open.");
});
}
));
let luks_manual_password_main_context = glib::MainContext::default();
// The main loop executes the asynchronous block
luks_manual_password_main_context.spawn_local(clone!(
#[weak]
crypttab_dialog,
async move {
while let Ok(state) = luks_manual_password_receiver.recv().await {
crypttab_dialog.set_response_enabled("crypttab_dialog_auto", state);
}
}
));
let partition_method_manual_crypttab_entry_array_refcell_clone0 =
partition_method_manual_crypttab_entry_array_refcell.clone();
let partition_method_manual_luks_enabled_refcell_clone0 =
partition_method_manual_luks_enabled_refcell.clone();
crypttab_dialog.choose(None::<&gio::Cancellable>, move |choice| {
let part_name = fs_entry.partition.part_name;
if choice == "crypttab_dialog_auto" {
(*partition_method_manual_crypttab_entry_array_refcell_clone0
.borrow_mut())
.push(CrypttabEntry {
partition: part_name.clone(),
map: part_name.replace("mapper/", ""),
uuid: get_luks_uuid(&part_name),
password: Some(crypttab_password.text().to_string()),
});
} else {
(*partition_method_manual_crypttab_entry_array_refcell_clone0
.borrow_mut())
.push(CrypttabEntry {
partition: part_name.clone(),
map: part_name.replace("mapper/", ""),
uuid: get_luks_uuid(&part_name),
password: None,
});
}
(*partition_method_manual_luks_enabled_refcell_clone0.borrow_mut()) = true;
});
}
}