Development over
This commit is contained in:
178
linux-hello-settings/src/templates.rs
Normal file
178
linux-hello-settings/src/templates.rs
Normal 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");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user