mirror of
https://github.com/YGGverse/Yoda.git
synced 2025-01-15 17:20:08 +00:00
draft certificate export feature
This commit is contained in:
parent
7420ce8606
commit
8a62ef46df
@ -1,10 +1,12 @@
|
||||
mod file;
|
||||
pub mod list;
|
||||
mod name;
|
||||
mod save;
|
||||
|
||||
use file::File;
|
||||
use list::{item::value::Value, List};
|
||||
use name::Name;
|
||||
use save::Save;
|
||||
|
||||
use super::Action;
|
||||
use gtk::{prelude::BoxExt, Box, Orientation};
|
||||
@ -15,6 +17,7 @@ pub struct Form {
|
||||
pub file: Rc<File>,
|
||||
pub list: Rc<List>,
|
||||
pub name: Rc<Name>,
|
||||
pub save: Rc<Save>,
|
||||
pub gobject: Box,
|
||||
}
|
||||
|
||||
@ -24,9 +27,10 @@ impl Form {
|
||||
/// Create new `Self`
|
||||
pub fn new(action: Rc<Action>) -> Self {
|
||||
// Init components
|
||||
let file = Rc::new(File::new(action.clone()));
|
||||
let list = Rc::new(List::new());
|
||||
let name = Rc::new(Name::new(action.clone()));
|
||||
let file = Rc::new(File::new(action.clone()));
|
||||
let save = Rc::new(Save::new(action.clone()));
|
||||
|
||||
// Init main container
|
||||
let gobject = Box::builder().orientation(Orientation::Vertical).build();
|
||||
@ -34,11 +38,13 @@ impl Form {
|
||||
gobject.append(&list.gobject);
|
||||
gobject.append(&name.gobject);
|
||||
gobject.append(&file.gobject);
|
||||
gobject.append(&save.gobject);
|
||||
|
||||
// Connect events
|
||||
list.on_select({
|
||||
let file = file.clone();
|
||||
let name = name.clone();
|
||||
let save = save.clone();
|
||||
let update = action.update.clone();
|
||||
move |item| {
|
||||
// Change name entry visibility
|
||||
@ -47,6 +53,16 @@ impl Form {
|
||||
// Change file choose button visibility
|
||||
file.show(matches!(item, Value::ImportPem));
|
||||
|
||||
// Change export button visibility, update holder @TODO
|
||||
match item {
|
||||
Value::ProfileIdentityGeminiId(id) => {
|
||||
// save.show(Some(id));
|
||||
}
|
||||
_ => {
|
||||
// save.show(None);
|
||||
}
|
||||
}
|
||||
|
||||
// Update widget
|
||||
update.activate();
|
||||
}
|
||||
@ -59,6 +75,7 @@ impl Form {
|
||||
file,
|
||||
list,
|
||||
name,
|
||||
save,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,126 @@
|
||||
mod certificate;
|
||||
use certificate::Certificate;
|
||||
|
||||
use super::Action;
|
||||
use gtk::{
|
||||
gio::{Cancellable, ListStore},
|
||||
prelude::{ButtonExt, FileExt, WidgetExt},
|
||||
Button, FileDialog, FileFilter, Window,
|
||||
};
|
||||
use std::{cell::RefCell, fs::File, io::Write, rc::Rc};
|
||||
|
||||
const LABEL: &str = "Export to file..";
|
||||
const MARGIN: i32 = 8;
|
||||
|
||||
pub struct Save {
|
||||
certificate: Rc<RefCell<Option<Certificate>>>,
|
||||
pub gobject: Button,
|
||||
}
|
||||
|
||||
impl Save {
|
||||
// Constructors
|
||||
|
||||
/// Create new `Self`
|
||||
pub fn new(action: Rc<Action>) -> Self {
|
||||
// Init `Certificate` holder
|
||||
let certificate = Rc::new(RefCell::new(None::<Certificate>));
|
||||
|
||||
// Init `GObject`
|
||||
let gobject = Button::builder()
|
||||
.label(LABEL)
|
||||
.margin_top(MARGIN)
|
||||
.visible(false)
|
||||
.build();
|
||||
|
||||
// Init events
|
||||
gobject.connect_clicked({
|
||||
let certificate = certificate.clone();
|
||||
let gobject = gobject.clone();
|
||||
move |_| {
|
||||
// Get certificate selected from holder
|
||||
match certificate.borrow().as_ref() {
|
||||
Some(certificate) => {
|
||||
// Copy certificate holder values
|
||||
let name = certificate.name.clone();
|
||||
let data = certificate.data.clone();
|
||||
|
||||
// Lock open button (prevent double click)
|
||||
gobject.set_sensitive(false);
|
||||
|
||||
// Init file filters related with PEM extension
|
||||
let filters = ListStore::new::<FileFilter>();
|
||||
|
||||
let filter_all = FileFilter::new();
|
||||
filter_all.add_pattern("*.*");
|
||||
filter_all.set_name(Some("All"));
|
||||
filters.append(&filter_all);
|
||||
|
||||
let filter_pem = FileFilter::new();
|
||||
filter_pem.add_mime_type("application/x-x509-ca-cert");
|
||||
filter_pem.set_name(Some("Certificate (*.pem)"));
|
||||
filters.append(&filter_pem);
|
||||
|
||||
// Init file dialog
|
||||
FileDialog::builder()
|
||||
.default_filter(&filter_pem)
|
||||
.filters(&filters)
|
||||
.initial_name(format!("{name}.pem"))
|
||||
.build()
|
||||
.save(None::<&Window>, None::<&Cancellable>, {
|
||||
let gobject = gobject.clone();
|
||||
move |result| {
|
||||
match result {
|
||||
Ok(file) => match file.path() {
|
||||
Some(path) => match File::create(&path) {
|
||||
Ok(mut destination) => {
|
||||
match destination.write_all(data.as_bytes()) {
|
||||
Ok(_) => {
|
||||
// @TODO
|
||||
gobject.set_css_classes(&["success"]);
|
||||
gobject.set_label(&format!(
|
||||
"Saved to {}",
|
||||
path.to_string_lossy()
|
||||
))
|
||||
}
|
||||
Err(reason) => {
|
||||
gobject.set_css_classes(&["error"]);
|
||||
gobject.set_label(&reason.to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(reason) => {
|
||||
gobject.set_css_classes(&["error"]);
|
||||
gobject.set_label(&reason.to_string())
|
||||
}
|
||||
},
|
||||
None => todo!(),
|
||||
},
|
||||
Err(reason) => {
|
||||
gobject.set_css_classes(&["warning"]);
|
||||
gobject.set_label(reason.message())
|
||||
}
|
||||
}
|
||||
gobject.set_sensitive(true); // unlock
|
||||
}
|
||||
});
|
||||
}
|
||||
None => todo!(), // unexpected
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Return activated `Self`
|
||||
Self {
|
||||
certificate,
|
||||
gobject,
|
||||
}
|
||||
}
|
||||
|
||||
// Actions
|
||||
|
||||
/// Change visibility status
|
||||
/// * grab focus on `is_visible`
|
||||
pub fn show(&self, is_visible: bool) {
|
||||
self.gobject.set_visible(is_visible)
|
||||
}
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
pub struct Certificate {
|
||||
pub name: String,
|
||||
pub data: String,
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user