From 6b5e712cdfec812a816dd3ce07c3e36e7f23f14d Mon Sep 17 00:00:00 2001 From: yggverse Date: Mon, 18 Nov 2024 11:44:33 +0200 Subject: [PATCH] implement records list builder, make some members public, drop extra getters --- Cargo.toml | 5 ++ .../window/tab/item/identity/gemini.rs | 47 ++++++++++- .../window/tab/item/identity/gemini/widget.rs | 17 ++-- .../tab/item/identity/gemini/widget/form.rs | 29 +++---- .../item/identity/gemini/widget/form/list.rs | 82 ++++++------------- .../item/identity/gemini/widget/form/name.rs | 8 +- src/profile/identity/gemini/database.rs | 2 +- 7 files changed, 96 insertions(+), 94 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 500c5184..16600115 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,11 @@ package = "gtk4" version = "0.9.1" features = ["v4_10"] +[dependencies.gio] +package = "gio" +version = "0.20.4" +features = ["v2_70"] + [dependencies.sqlite] package = "rusqlite" version = "0.32.1" diff --git a/src/app/browser/window/tab/item/identity/gemini.rs b/src/app/browser/window/tab/item/identity/gemini.rs index 46e8f3ba..c10fb7a5 100644 --- a/src/app/browser/window/tab/item/identity/gemini.rs +++ b/src/app/browser/window/tab/item/identity/gemini.rs @@ -2,11 +2,15 @@ mod widget; use widget::Widget; use crate::profile::Profile; -use gtk::{glib::Uri, prelude::IsA}; +use gtk::{ + gio::{prelude::TlsCertificateExt, TlsCertificate}, + glib::Uri, + prelude::IsA, +}; use std::rc::Rc; pub struct Gemini { - profile: Rc, + // profile: Rc, widget: Rc, } @@ -15,8 +19,42 @@ impl Gemini { /// Create new `Self` for given Profile pub fn new(profile: Rc, auth_uri: Uri) -> Self { + // Init widget let widget = Rc::new(Widget::new()); + // Add new identity option + widget.form.list.append(None, "Create new.."); + + // Collect additional options from database + match profile.identity.gemini.database.records() { + Ok(identities) => { + for identity in identities { + // Get certificate details + let certificate = match TlsCertificate::from_pem(&identity.pem) { + Ok(certificate) => certificate, + Err(reason) => todo!("{reason}"), + }; + + // Get expiration time + let expires = certificate + .not_valid_after() + .unwrap() + .format_iso8601() + .unwrap(); + + // Append record option + widget.form.list.append( + Some(identity.id), + &match identity.name { + Some(name) => format!("{name} ({expires})"), + None => format!("{expires}"), + }, + ); + } + } + Err(_) => todo!(), + } + // Init events widget.connect_response({ let profile = profile.clone(); @@ -33,7 +71,10 @@ impl Gemini { }); // Return activated `Self` - Self { profile, widget } + Self { + // profile, + widget, + } } // Actions diff --git a/src/app/browser/window/tab/item/identity/gemini/widget.rs b/src/app/browser/window/tab/item/identity/gemini/widget.rs index b3610cb1..889aae7c 100644 --- a/src/app/browser/window/tab/item/identity/gemini/widget.rs +++ b/src/app/browser/window/tab/item/identity/gemini/widget.rs @@ -7,6 +7,7 @@ use adw::{ AlertDialog, ResponseAppearance, }; use gtk::prelude::IsA; +use std::rc::Rc; // Defaults const HEADING: &str = "Ident"; @@ -17,13 +18,11 @@ const RESPONSE_APPLY: (&str, &str) = ("apply", "Apply"); const RESPONSE_CANCEL: (&str, &str) = ("cancel", "Cancel"); // const RESPONSE_MANAGE: (&str, &str) = ("manage", "Manage"); -// List options -const OPTION_CREATE: (Option, &str) = (None, "Create new.."); - // Select options pub struct Widget { - gobject: AlertDialog, + pub form: Rc
, + pub gobject: AlertDialog, } impl Widget { @@ -31,12 +30,8 @@ impl Widget { /// Create new `Self` pub fn new() -> Self { - // Collect identity certificates - let mut options: Vec<(Option, String, bool)> = Vec::new(); - options.push((OPTION_CREATE.0, OPTION_CREATE.1.to_owned(), false)); - // Init child container - let form = Form::new(options); + let form = Rc::new(Form::new()); // Init main `GObject` let gobject = AlertDialog::builder() @@ -44,7 +39,7 @@ impl Widget { .body(BODY) .close_response(RESPONSE_CANCEL.0) .default_response(RESPONSE_APPLY.0) - .extra_child(form.gobject()) + .extra_child(&form.gobject) .build(); // Set response variants @@ -62,7 +57,7 @@ impl Widget { gobject.set_response_appearance(RESPONSE_CANCEL.0, ResponseAppearance::Destructive); // Return new activated `Self` - Self { gobject } + Self { form, gobject } } // Actions diff --git a/src/app/browser/window/tab/item/identity/gemini/widget/form.rs b/src/app/browser/window/tab/item/identity/gemini/widget/form.rs index 97f47071..53fbc877 100644 --- a/src/app/browser/window/tab/item/identity/gemini/widget/form.rs +++ b/src/app/browser/window/tab/item/identity/gemini/widget/form.rs @@ -8,36 +8,37 @@ use gtk::{ prelude::{BoxExt, WidgetExt}, Box, Orientation, }; +use std::rc::Rc; pub struct Form { - gobject: Box, + pub gobject: Box, + pub list: Rc, + // pub name: Rc, } impl Form { // Constructors /// Create new `Self` - pub fn new(items: Vec<(Option, String, bool)>) -> Self { + pub fn new() -> Self { // Init components - let list = List::new(); - let name = Name::new(); + let list = Rc::new(List::new()); + let name = Rc::new(Name::new()); // Init main container let gobject = Box::builder().orientation(Orientation::Vertical).build(); - gobject.append(list.gobject()); - gobject.append(name.gobject()); + gobject.append(&list.gobject); + gobject.append(&name.gobject); // Connect events - list.on_select(move |key| name.gobject().set_visible(key.is_none())); + list.connect_selected_notify(move |key| name.gobject.set_visible(key.is_none())); // Return activated `Self` - Self { gobject } - } - - // Getters - - pub fn gobject(&self) -> &Box { - &self.gobject + Self { + gobject, + list, + // name, + } } } diff --git a/src/app/browser/window/tab/item/identity/gemini/widget/form/list.rs b/src/app/browser/window/tab/item/identity/gemini/widget/form/list.rs index 57cf347f..378c9d79 100644 --- a/src/app/browser/window/tab/item/identity/gemini/widget/form/list.rs +++ b/src/app/browser/window/tab/item/identity/gemini/widget/form/list.rs @@ -1,11 +1,10 @@ -use gtk::{gio::ListStore, prelude::ObjectExt, DropDown, Label}; - -const PROPERTY_KEY_NAME: &str = "key"; // Store item key as GTK property -const PROPERTY_KEY_NONE_VALUE: i64 = -1; // C-type conversion for `None` values +use gtk::{gio::ListStore, DropDown, Label}; +use std::{cell::RefCell, collections::HashMap, rc::Rc}; pub struct List { - gobject: DropDown, + pub gobject: DropDown, model: ListStore, + index: Rc>>>, } impl List { @@ -13,74 +12,41 @@ impl List { /// Create new `Self` pub fn new() -> Self { + let index = Rc::new(RefCell::new(HashMap::new())); let model = ListStore::new::