|
@@ -185,9 +185,10 @@ impl KioskLoginView {
|
|
|
let mut result = LoginResult::None;
|
|
let mut result = LoginResult::None;
|
|
|
|
|
|
|
|
ui.vertical_centered(|ui| {
|
|
ui.vertical_centered(|ui| {
|
|
|
- ui.add_space(50.0);
|
|
|
|
|
- ui.heading(egui::RichText::new(&self.ui_settings.title).size(32.0));
|
|
|
|
|
- ui.add_space(30.0);
|
|
|
|
|
|
|
+ let spacing_scale = self.ui_settings.scaling_factor.max(1.0);
|
|
|
|
|
+ ui.add_space(50.0 * spacing_scale);
|
|
|
|
|
+ ui.heading(egui::RichText::new(&self.ui_settings.title).size(self.ui_settings.font_size * 1.5));
|
|
|
|
|
+ ui.add_space(30.0 * spacing_scale);
|
|
|
|
|
|
|
|
if self.is_rfid_mode {
|
|
if self.is_rfid_mode {
|
|
|
result = self.show_rfid_entry(ui, client);
|
|
result = self.show_rfid_entry(ui, client);
|
|
@@ -217,10 +218,11 @@ impl KioskLoginView {
|
|
|
|
|
|
|
|
egui::ScrollArea::vertical().show(ui, |ui| {
|
|
egui::ScrollArea::vertical().show(ui, |ui| {
|
|
|
ui.vertical_centered(|ui| {
|
|
ui.vertical_centered(|ui| {
|
|
|
|
|
+ let btn_width = 300.0 * self.ui_settings.scaling_factor.max(1.0);
|
|
|
for user in &self.users {
|
|
for user in &self.users {
|
|
|
let btn = egui::Button::new(
|
|
let btn = egui::Button::new(
|
|
|
egui::RichText::new(&user.name).size(self.ui_settings.font_size * 0.8)
|
|
egui::RichText::new(&user.name).size(self.ui_settings.font_size * 0.8)
|
|
|
- ).min_size(egui::vec2(300.0, self.ui_settings.button_height));
|
|
|
|
|
|
|
+ ).min_size(egui::vec2(btn_width, self.ui_settings.button_height));
|
|
|
|
|
|
|
|
if ui.add(btn).clicked() {
|
|
if ui.add(btn).clicked() {
|
|
|
self.selected_user = Some(user.clone());
|
|
self.selected_user = Some(user.clone());
|
|
@@ -234,7 +236,7 @@ impl KioskLoginView {
|
|
|
ui.add_space(20.0);
|
|
ui.add_space(20.0);
|
|
|
let btn = egui::Button::new(
|
|
let btn = egui::Button::new(
|
|
|
egui::RichText::new("Badge Log In").size(self.ui_settings.font_size * 0.8)
|
|
egui::RichText::new("Badge Log In").size(self.ui_settings.font_size * 0.8)
|
|
|
- ).min_size(egui::vec2(300.0, self.ui_settings.button_height));
|
|
|
|
|
|
|
+ ).min_size(egui::vec2(btn_width, self.ui_settings.button_height));
|
|
|
|
|
|
|
|
if ui.add(btn).clicked() {
|
|
if ui.add(btn).clicked() {
|
|
|
self.is_rfid_mode = true;
|
|
self.is_rfid_mode = true;
|
|
@@ -270,10 +272,13 @@ impl KioskLoginView {
|
|
|
// Ensure the Cancel button never goes off-screen: shrink if needed
|
|
// Ensure the Cancel button never goes off-screen: shrink if needed
|
|
|
let mut cancel_h = self.ui_settings.button_height;
|
|
let mut cancel_h = self.ui_settings.button_height;
|
|
|
let avail_h = ui.available_height();
|
|
let avail_h = ui.available_height();
|
|
|
- if avail_h < cancel_h + 12.0 {
|
|
|
|
|
- cancel_h = (avail_h - 12.0).max(36.0);
|
|
|
|
|
|
|
+ let margin = 12.0;
|
|
|
|
|
+ let min_button_h = 36.0;
|
|
|
|
|
+ if avail_h < cancel_h + margin {
|
|
|
|
|
+ cancel_h = (avail_h - margin).max(min_button_h);
|
|
|
}
|
|
}
|
|
|
- if ui.add_sized(egui::vec2(150.0, cancel_h), egui::Button::new(egui::RichText::new("Cancel").size((self.ui_settings.font_size * 0.8).min(cancel_h * 0.6)))).clicked() {
|
|
|
|
|
|
|
+ let cancel_width = 150.0 * self.ui_settings.scaling_factor.max(1.0);
|
|
|
|
|
+ if ui.add_sized(egui::vec2(cancel_width, cancel_h), egui::Button::new(egui::RichText::new("Cancel").size((self.ui_settings.font_size * 0.8).min(cancel_h * 0.6)))).clicked() {
|
|
|
self.is_rfid_mode = false;
|
|
self.is_rfid_mode = false;
|
|
|
self.rfid_input.clear();
|
|
self.rfid_input.clear();
|
|
|
self.error_message = None;
|
|
self.error_message = None;
|
|
@@ -308,37 +313,64 @@ impl KioskLoginView {
|
|
|
ui.add_space(10.0);
|
|
ui.add_space(10.0);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Reserve a bottom strip and place action buttons centered, respecting button_height
|
|
|
|
|
- let result = ui.allocate_ui_with_layout(
|
|
|
|
|
- egui::vec2(ui.available_width(), self.ui_settings.button_height),
|
|
|
|
|
- egui::Layout::bottom_up(egui::Align::Center),
|
|
|
|
|
- |ui| {
|
|
|
|
|
|
|
+ // Bottom action buttons - Docked to bottom, Centered
|
|
|
|
|
+ let avail_width = ui.available_width();
|
|
|
|
|
+ let avail_height = ui.available_height();
|
|
|
|
|
+ let scaling = self.ui_settings.scaling_factor.max(1.0);
|
|
|
|
|
+
|
|
|
|
|
+ // Calculate sizes
|
|
|
|
|
+ let btn_h = self.ui_settings.button_height;
|
|
|
|
|
+ let btn_w = 150.0 * scaling;
|
|
|
|
|
+ let spacing = 20.0 * scaling;
|
|
|
|
|
+ let bottom_padding = 20.0 * scaling;
|
|
|
|
|
+
|
|
|
|
|
+ // Allocate the bottom strip
|
|
|
|
|
+ let footer_height = btn_h + bottom_padding;
|
|
|
|
|
+
|
|
|
|
|
+ // Use allocate_ui_at_rect to force placement at the bottom
|
|
|
|
|
+ let footer_rect = egui::Rect::from_min_size(
|
|
|
|
|
+ egui::Pos2::new(ui.min_rect().left(), ui.max_rect().bottom() - footer_height),
|
|
|
|
|
+ egui::vec2(avail_width, footer_height)
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ // We need to be careful not to draw over existing content if the screen is too small,
|
|
|
|
|
+ // but for a Kiosk login screen, we assume some vertical space.
|
|
|
|
|
+ // Using allocate_ui_at_rect allows precise positioning.
|
|
|
|
|
+
|
|
|
|
|
+ let result = ui.allocate_ui_at_rect(footer_rect, |ui| {
|
|
|
|
|
+ ui.vertical_centered(|ui| {
|
|
|
|
|
+ ui.add_space(bottom_padding / 2.0); // center vertically in the footer strip roughly
|
|
|
ui.horizontal(|ui| {
|
|
ui.horizontal(|ui| {
|
|
|
- let btn_h = self.ui_settings.button_height;
|
|
|
|
|
- let btn_size = egui::vec2(150.0, btn_h);
|
|
|
|
|
- let label_size = (self.ui_settings.font_size * 0.8).min(btn_h * 0.6);
|
|
|
|
|
|
|
+ // Manually center the horizontal row by adding flexible space or calculating margin
|
|
|
|
|
+ let total_content_width = (btn_w * 2.0) + spacing;
|
|
|
|
|
+ let margin = (ui.available_width() - total_content_width) / 2.0;
|
|
|
|
|
+ if margin > 0.0 {
|
|
|
|
|
+ ui.add_space(margin);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- let total_width = btn_size.x * 2.0 + 30.0; // 2 buttons + spacing
|
|
|
|
|
- let available_width = ui.available_width();
|
|
|
|
|
- let margin = (available_width - total_width) / 2.0;
|
|
|
|
|
- if margin > 0.0 { ui.add_space(margin); }
|
|
|
|
|
|
|
+ let label_size = (self.ui_settings.font_size * 0.8).min(btn_h * 0.6);
|
|
|
|
|
|
|
|
- if ui.add_sized(btn_size, egui::Button::new(egui::RichText::new("Back").size(label_size))).clicked() {
|
|
|
|
|
|
|
+ if ui.add_sized(egui::vec2(btn_w, btn_h), egui::Button::new(egui::RichText::new("Back").size(label_size))).clicked() {
|
|
|
self.selected_user = None;
|
|
self.selected_user = None;
|
|
|
self.pin_input.clear();
|
|
self.pin_input.clear();
|
|
|
self.error_message = None;
|
|
self.error_message = None;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- ui.add_space(20.0);
|
|
|
|
|
|
|
+ ui.add_space(spacing);
|
|
|
|
|
|
|
|
- if ui.add_sized(btn_size, egui::Button::new(egui::RichText::new("Login").size(label_size))).clicked() {
|
|
|
|
|
|
|
+ if ui.add_sized(egui::vec2(btn_w, btn_h), egui::Button::new(egui::RichText::new("Login").size(label_size))).clicked() {
|
|
|
return self.attempt_login(client);
|
|
return self.attempt_login(client);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
LoginResult::None
|
|
LoginResult::None
|
|
|
}).inner
|
|
}).inner
|
|
|
- }
|
|
|
|
|
- ).inner;
|
|
|
|
|
|
|
+ }).inner
|
|
|
|
|
+ }).inner;
|
|
|
|
|
+
|
|
|
|
|
+ // Ensure we return the result from the button click if any
|
|
|
|
|
+ if let LoginResult::Success(_, _) = &result {
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
if let Some(error) = &self.error_message {
|
|
if let Some(error) = &self.error_message {
|
|
|
ui.add_space(10.0);
|
|
ui.add_space(10.0);
|
|
@@ -364,11 +396,21 @@ impl KioskLoginView {
|
|
|
let spacing = ui.style().spacing.item_spacing;
|
|
let spacing = ui.style().spacing.item_spacing;
|
|
|
let avail_h = ui.available_height();
|
|
let avail_h = ui.available_height();
|
|
|
let avail_w = ui.available_width();
|
|
let avail_w = ui.available_width();
|
|
|
- // Reserve space for bottom action buttons and padding after OSK
|
|
|
|
|
- let reserved_bottom = self.ui_settings.button_height + 120.0;
|
|
|
|
|
- let max_h_per_key = ((avail_h - reserved_bottom) - spacing.y * (rows - 1.0)) / rows;
|
|
|
|
|
|
|
+ let scaling = self.ui_settings.scaling_factor.max(1.0);
|
|
|
|
|
+ let pin_scaling = self.ui_settings.pin_pad_scaling_factor.unwrap_or(scaling).max(1.0);
|
|
|
|
|
+
|
|
|
|
|
+ // Calculate minimal reserved space for the bottom elements
|
|
|
|
|
+ // This allows the keypad to take up all remaining vertical space if needed.
|
|
|
|
|
+ // Footer = Button Height + 20 Padding + 10 Spacer
|
|
|
|
|
+ let footer_reserve = self.ui_settings.button_height + (30.0 * scaling);
|
|
|
|
|
+
|
|
|
|
|
+ let max_h_per_key = ((avail_h - footer_reserve) - spacing.y * (rows - 1.0)) / rows;
|
|
|
let max_w_per_key = (avail_w - spacing.x * (cols - 1.0)) / cols;
|
|
let max_w_per_key = (avail_w - spacing.x * (cols - 1.0)) / cols;
|
|
|
- let key_edge = max_h_per_key.min(max_w_per_key).clamp(12.0, 80.0);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // Use a much larger maximum limit so keys fill the screen on large kiosks
|
|
|
|
|
+ // But keep them square.
|
|
|
|
|
+ let key_edge = max_h_per_key.min(max_w_per_key).max(60.0 * pin_scaling);
|
|
|
|
|
+
|
|
|
let btn_size = egui::vec2(key_edge, key_edge);
|
|
let btn_size = egui::vec2(key_edge, key_edge);
|
|
|
|
|
|
|
|
ui.vertical_centered(|ui| {
|
|
ui.vertical_centered(|ui| {
|
|
@@ -383,7 +425,8 @@ impl KioskLoginView {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
for key in row {
|
|
for key in row {
|
|
|
- let key_font = (self.ui_settings.font_size * 0.8).min(btn_size.y * 0.6).max(16.0);
|
|
|
|
|
|
|
+ // Allow font to be as large as configured, or fitted to button
|
|
|
|
|
+ let key_font = self.ui_settings.font_size.min(btn_size.y * 0.5).max(24.0 * pin_scaling);
|
|
|
if ui.add_sized(btn_size, egui::Button::new(egui::RichText::new(key).size(key_font))).clicked() {
|
|
if ui.add_sized(btn_size, egui::Button::new(egui::RichText::new(key).size(key_font))).clicked() {
|
|
|
match key {
|
|
match key {
|
|
|
"C" => self.pin_input.clear(),
|
|
"C" => self.pin_input.clear(),
|