add auth widget actions

This commit is contained in:
yggverse 2024-11-21 12:03:09 +02:00
parent 5d01786596
commit 17f356dde7
5 changed files with 123 additions and 16 deletions

View File

@ -1,4 +1,7 @@
mod action;
pub mod form;
use action::Action;
use form::{list::item::value::Value, Form};
use adw::{
@ -20,6 +23,7 @@ const RESPONSE_CANCEL: (&str, &str) = ("cancel", "Cancel");
// Select options
pub struct Widget {
// pub action: Rc<Action>,
pub form: Rc<Form>,
pub gobject: AlertDialog,
}
@ -29,8 +33,11 @@ impl Widget {
/// Create new `Self`
pub fn new() -> Self {
// Init actions
let action = Rc::new(Action::new());
// Init child container
let form = Rc::new(Form::new());
let form = Rc::new(Form::new(action.clone()));
// Init main `GObject`
let gobject = AlertDialog::builder()
@ -55,8 +62,22 @@ impl Widget {
gobject.set_response_appearance(RESPONSE_APPLY.0, ResponseAppearance::Suggested);
gobject.set_response_appearance(RESPONSE_CANCEL.0, ResponseAppearance::Destructive);
// Init events
action.update.connect_activate({
let form = form.clone();
let gobject = gobject.clone();
move || {
// Deactivate apply button if the form values could not be processed
gobject.set_response_enabled(RESPONSE_APPLY.0, form.is_valid());
}
});
// Return new activated `Self`
Self { form, gobject }
Self {
// action,
form,
gobject,
}
}
// Actions

View File

@ -0,0 +1,20 @@
mod update;
use update::Update;
use std::rc::Rc;
/// [SimpleActionGroup](https://docs.gtk.org/gio/class.SimpleActionGroup.html) wrapper
pub struct Action {
pub update: Rc<Update>,
}
impl Action {
// Constructors
/// Create new `Self`
pub fn new() -> Self {
Self {
update: Rc::new(Update::new()),
}
}
}

View File

@ -0,0 +1,33 @@
use gtk::{gio::SimpleAction, glib::uuid_string_random, prelude::ActionExt};
/// [SimpleAction](https://docs.gtk.org/gio/class.SimpleAction.html) wrapper for `Update` action
pub struct Update {
pub gobject: SimpleAction,
}
impl Update {
// Constructors
/// Create new `Self`
pub fn new() -> Self {
Self {
gobject: SimpleAction::new(&uuid_string_random(), None),
}
}
// Actions
/// Emit [activate](https://docs.gtk.org/gio/signal.SimpleAction.activate.html) signal
/// with formatted for this action [Variant](https://docs.gtk.org/glib/struct.Variant.html) value
pub fn activate(&self) {
self.gobject.activate(None);
}
// Events
/// Define callback function for
/// [SimpleAction::activate](https://docs.gtk.org/gio/signal.SimpleAction.activate.html) signal
pub fn connect_activate(&self, callback: impl Fn() + 'static) {
self.gobject.connect_activate(move |_, _| callback());
}
}

View File

@ -4,6 +4,7 @@ mod name;
use list::{item::value::Value, List};
use name::Name;
use super::Action;
use gtk::{
prelude::{BoxExt, WidgetExt},
Box, Orientation,
@ -11,19 +12,20 @@ use gtk::{
use std::rc::Rc;
pub struct Form {
pub gobject: Box,
// pub action: Rc<Action>,
pub list: Rc<List>,
pub name: Rc<Name>,
pub gobject: Box,
}
impl Form {
// Constructors
/// Create new `Self`
pub fn new() -> Self {
pub fn new(action: Rc<Action>) -> Self {
// Init components
let list = Rc::new(List::new());
let name = Rc::new(Name::new());
let name = Rc::new(Name::new(action.clone()));
// Init main container
let gobject = Box::builder().orientation(Orientation::Vertical).build();
@ -34,19 +36,31 @@ impl Form {
// Connect events
list.on_select({
let name = name.clone();
let update = action.update.clone();
move |key| {
// Change name entry visibility
name.gobject.set_visible(match key {
Value::GENERATE_NEW_AUTH => true,
_ => false,
})
});
// Update widget
update.activate();
}
});
// Return activated `Self`
Self {
// action,
gobject,
list,
name,
}
}
// Actions
pub fn is_valid(&self) -> bool {
self.name.is_valid() // @TODO
}
}

View File

@ -1,7 +1,15 @@
use gtk::{glib::GString, prelude::EditableExt, Entry};
use super::Action;
use gtk::{
glib::GString,
prelude::{EditableExt, EntryExt},
Entry,
};
use std::rc::Rc;
const PLACEHOLDER_TEXT: &str = "Identity name (optional)";
const PLACEHOLDER_TEXT: &str = "Identity name (required)";
const MARGIN: i32 = 8;
const MIN_LENGTH: u16 = 1;
const MAX_LENGTH: u16 = 36;
pub struct Name {
pub gobject: Entry,
@ -11,14 +19,25 @@ impl Name {
// Constructors
/// Create new `Self`
pub fn new() -> Self {
Self {
gobject: Entry::builder()
.max_length(36) // @TODO use profile const
.placeholder_text(PLACEHOLDER_TEXT)
.margin_top(MARGIN)
.build(),
}
pub fn new(action: Rc<Action>) -> Self {
// Init `GObject`
let gobject = Entry::builder()
.max_length(MAX_LENGTH as i32)
.placeholder_text(PLACEHOLDER_TEXT)
.margin_top(MARGIN)
.build();
// Init events
gobject.connect_changed(move |_| action.update.activate());
// Return activated `Self`
Self { gobject }
}
// Actions
pub fn is_valid(&self) -> bool {
self.gobject.text_length() >= MIN_LENGTH && self.gobject.text_length() <= MAX_LENGTH
}
// Getters