Development over

This commit is contained in:
2026-01-15 22:40:51 +01:00
parent 2f6b16d946
commit 1e7f296635
63 changed files with 12945 additions and 331 deletions

View File

@@ -0,0 +1,178 @@
//! Template List Widget
//!
//! Provides a widget for displaying and managing enrolled face templates.
//! Supports viewing template details and removing templates.
use crate::dbus_client::TemplateInfo;
/// Template list box containing enrolled templates
#[derive(Debug, Clone)]
pub struct TemplateListBox {
/// List of templates
templates: Vec<TemplateInfo>,
}
impl TemplateListBox {
/// Create a new template list box
pub fn new(templates: Vec<TemplateInfo>) -> Self {
Self { templates }
}
/// Get the list of templates
pub fn templates(&self) -> &[TemplateInfo] {
&self.templates
}
/// Find a template by ID
pub fn find_by_id(&self, id: &str) -> Option<&TemplateInfo> {
self.templates.iter().find(|t| t.id == id)
}
/// Find a template by label
pub fn find_by_label(&self, label: &str) -> Option<&TemplateInfo> {
self.templates.iter().find(|t| t.label == label)
}
/// Check if any templates are enrolled
pub fn is_empty(&self) -> bool {
self.templates.is_empty()
}
/// Get the count of enrolled templates
pub fn count(&self) -> usize {
self.templates.len()
}
/// Update the template list
pub fn update(&mut self, templates: Vec<TemplateInfo>) {
self.templates = templates;
}
}
impl Default for TemplateListBox {
fn default() -> Self {
Self::new(Vec::new())
}
}
/// Template display model for UI binding
#[derive(Debug, Clone)]
pub struct TemplateDisplayModel {
/// Template ID
pub id: String,
/// Display label
pub label: String,
/// Username
pub username: String,
/// Formatted creation date
pub created_date: String,
/// Formatted last used date
pub last_used_date: String,
/// Whether this template has been used recently
pub recently_used: bool,
}
impl TemplateDisplayModel {
/// Create a display model from template info
pub fn from_template(template: &TemplateInfo) -> Self {
use chrono::{DateTime, Duration, Local, Utc};
let created_date = DateTime::<Utc>::from_timestamp(template.created_at, 0)
.map(|dt| dt.with_timezone(&Local))
.map(|dt| dt.format("%B %d, %Y").to_string())
.unwrap_or_else(|| "Unknown".to_string());
let (last_used_date, recently_used) = if let Some(ts) = template.last_used {
let dt = DateTime::<Utc>::from_timestamp(ts, 0)
.map(|dt| dt.with_timezone(&Local));
let date_str = dt
.as_ref()
.map(|d| d.format("%B %d, %Y at %H:%M").to_string())
.unwrap_or_else(|| "Unknown".to_string());
// Check if used within the last 24 hours
let recent = dt
.map(|d| {
let now = Local::now();
now.signed_duration_since(d) < Duration::hours(24)
})
.unwrap_or(false);
(date_str, recent)
} else {
("Never".to_string(), false)
};
Self {
id: template.id.clone(),
label: template.label.clone(),
username: template.username.clone(),
created_date,
last_used_date,
recently_used,
}
}
}
/// Template action types
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TemplateAction {
/// View template details
View,
/// Remove template
Remove,
/// Test authentication with template
Test,
}
#[cfg(test)]
mod tests {
use super::*;
fn create_test_template(id: &str, label: &str) -> TemplateInfo {
TemplateInfo {
id: id.to_string(),
label: label.to_string(),
username: "testuser".to_string(),
created_at: 1704067200, // 2024-01-01 00:00:00 UTC
last_used: Some(1704153600), // 2024-01-02 00:00:00 UTC
}
}
#[test]
fn test_template_list_box() {
let templates = vec![
create_test_template("1", "default"),
create_test_template("2", "backup"),
];
let list = TemplateListBox::new(templates);
assert!(!list.is_empty());
assert_eq!(list.count(), 2);
assert!(list.find_by_id("1").is_some());
assert!(list.find_by_label("backup").is_some());
assert!(list.find_by_id("nonexistent").is_none());
}
#[test]
fn test_empty_list() {
let list = TemplateListBox::default();
assert!(list.is_empty());
assert_eq!(list.count(), 0);
}
#[test]
fn test_template_display_model() {
let template = create_test_template("test-id", "Test Face");
let model = TemplateDisplayModel::from_template(&template);
assert_eq!(model.id, "test-id");
assert_eq!(model.label, "Test Face");
assert_eq!(model.username, "testuser");
assert!(!model.created_date.is_empty());
assert_ne!(model.last_used_date, "Never");
}
}