UMTS at Teleco 3 周之前
父节点
当前提交
4298d8c293
共有 2 个文件被更改,包括 252 次插入0 次删除
  1. 39 0
      src/kioskui/app.rs
  2. 213 0
      src/kioskui/dashboard.rs

+ 39 - 0
src/kioskui/app.rs

@@ -116,16 +116,55 @@ impl eframe::App for KioskApp {
         if !self.window_setup_done {
             if self.config.ui.fullscreen {
                 ctx.send_viewport_cmd(egui::ViewportCommand::Fullscreen(true));
+<<<<<<< Updated upstream
             }
 
         // Enforce fullscreen again after a short delay (to handle some window managers)
         if !self.delayed_fullscreen_done && self.startup_time.elapsed().as_secs_f32() > 1.0 {
             if self.config.ui.fullscreen {
                 ctx.send_viewport_cmd(egui::ViewportCommand::Fullscreen(true));
+=======
+                ctx.send_viewport_cmd(egui::ViewportCommand::Decorations(false));
+            } else {
+                // Ensure we are not in fullscreen and re-enable window decorations (borders, title bar)
+                ctx.send_viewport_cmd(egui::ViewportCommand::Fullscreen(false));
+                ctx.send_viewport_cmd(egui::ViewportCommand::Decorations(true));
+                // Ask the window manager to maximize the window
+                ctx.send_viewport_cmd(egui::ViewportCommand::Maximized(true));
+            }
+
+            // Enforce desired mode again after a short delay (to handle some window managers)
+            if !self.delayed_fullscreen_done && self.startup_time.elapsed().as_secs_f32() > 1.0 {
+                if want_fullscreen {
+                    ctx.send_viewport_cmd(egui::ViewportCommand::Fullscreen(true));
+                    ctx.send_viewport_cmd(egui::ViewportCommand::Decorations(false));
+                } else {
+                    ctx.send_viewport_cmd(egui::ViewportCommand::Fullscreen(false));
+                    ctx.send_viewport_cmd(egui::ViewportCommand::Decorations(true));
+                    ctx.send_viewport_cmd(egui::ViewportCommand::Maximized(true));
+                }
+                self.delayed_fullscreen_done = true;
+>>>>>>> Stashed changes
             }
             self.delayed_fullscreen_done = true;
         }
+<<<<<<< Updated upstream
             self.window_setup_done = true;
+=======
+
+        // Periodically re-assert desired window mode in case the OS/window manager changed it.
+        if self.last_enforce_check.elapsed().as_secs_f32() > 3.0 {
+            let want_fullscreen = if self.config.ui.windowed_mode { false } else { self.config.ui.fullscreen };
+            if want_fullscreen {
+                ctx.send_viewport_cmd(egui::ViewportCommand::Fullscreen(true));
+                ctx.send_viewport_cmd(egui::ViewportCommand::Decorations(false));
+            } else {
+                ctx.send_viewport_cmd(egui::ViewportCommand::Fullscreen(false));
+                ctx.send_viewport_cmd(egui::ViewportCommand::Decorations(true));
+                ctx.send_viewport_cmd(egui::ViewportCommand::Maximized(true));
+            }
+            self.last_enforce_check = std::time::Instant::now();
+>>>>>>> Stashed changes
         }
 
         // Check for interaction (clicks or key presses, ignore mouse moves to prevent drift issues)

+ 213 - 0
src/kioskui/dashboard.rs

@@ -0,0 +1,213 @@
+use eframe::egui;
+use crate::api::ApiClient;
+use crate::core::workflows::borrow_flow::BorrowFlow;
+use crate::core::workflows::return_flow::ReturnFlow;
+use crate::models::UserInfo;
+use crate::config::KioskUiSettings;
+
+pub struct KioskDashboard {
+    pub borrow_flow: BorrowFlow,
+    pub return_flow: ReturnFlow,
+}
+
+impl KioskDashboard {
+    pub fn new() -> Self {
+        Self {
+            borrow_flow: BorrowFlow::default(),
+            return_flow: ReturnFlow::default(),
+        }
+    }
+
+    pub fn show(
+        &mut self,
+        ui: &mut egui::Ui,
+        api_client: &ApiClient,
+        user: &UserInfo,
+        config: &KioskUiSettings,
+        show_osk: &mut bool,
+        logout_requested: &mut bool,
+        show_full_ui_requested: &mut bool,
+    ) {
+        let avail_rect = ui.available_rect_before_wrap();
+        // Calculate row heights
+        // Structure: Row 1 (0.5h), Row 2 (1h), Row 3 (1h), Row 4 (1h)
+        // Total units = 3.5
+        let total_units = 3.5;
+        let unit_height = avail_rect.height() / total_units;
+        let header_height = unit_height * 0.5;
+        let row_height = unit_height;
+
+        // Kiosk-only header/button text should respect kiosk font_size
+        let btn_font_size = config.font_size.max(12.0);
+        let label_font_size = (config.font_size * 0.8).max(12.0);
+
+        // --- Row 1: Header (Logout, OSK) ---
+        ui.allocate_ui_at_rect(
+            egui::Rect::from_min_size(avail_rect.min, egui::vec2(avail_rect.width(), header_height)),
+            |ui| {
+                ui.horizontal(|ui| {
+                    ui.with_layout(egui::Layout::left_to_right(egui::Align::Center), |ui| {
+                        if ui.add_sized(egui::vec2(120.0, header_height - 20.0), egui::Button::new(egui::RichText::new("Logout").size(btn_font_size))).clicked() {
+                            *logout_requested = true;
+                        }
+                        
+                        ui.label(egui::RichText::new(format!("Logged in as: {}", user.username)).size(label_font_size));
+                    });
+                    
+                    ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
+                        if config.enable_osk {
+                            let btn_text = if *show_osk { "Hide Keyboard" } else { "Show Keyboard" };
+                            if ui.add_sized(egui::vec2(150.0, header_height - 20.0), egui::Button::new(egui::RichText::new(btn_text).size(btn_font_size))).clicked() {
+                                *show_osk = !*show_osk;
+                            }
+                        }
+                    });
+                });
+            }
+        );
+
+        // Content Area (Rows 2, 3, 4)
+        // If a workflow is open, it takes over the rest of the screen.
+        // Otherwise, show the Dashboard Buttons.
+        
+        let content_rect = egui::Rect::from_min_size(
+            avail_rect.min + egui::vec2(0.0, header_height), 
+            egui::vec2(avail_rect.width(), avail_rect.height() - header_height)
+        );
+
+        ui.allocate_ui_at_rect(content_rect, |ui| {
+            if self.borrow_flow.is_open {
+                // Apply optional view-level multiplier for reused desktop views
+                let vscale = config.view_scale_multiplier;
+                if (vscale - 1.0).abs() > f32::EPSILON {
+                    ui.scope(|ui| {
+                        let mut style: egui::Style = ui.style().as_ref().clone();
+                        for (_ts, font) in style.text_styles.iter_mut() {
+                            font.size *= vscale;
+                        }
+                        style.spacing.item_spacing *= vscale;
+                        style.spacing.button_padding *= vscale;
+                        style.spacing.indent *= vscale;
+                        style.spacing.window_margin = style.spacing.window_margin * vscale;
+                        ui.set_style(style);
+                        self.borrow_flow.show_content(ui, api_client);
+                    });
+                } else {
+                    self.borrow_flow.show_content(ui, api_client);
+                }
+            } else if self.return_flow.is_open {
+                let vscale = config.view_scale_multiplier;
+                if (vscale - 1.0).abs() > f32::EPSILON {
+                    ui.scope(|ui| {
+                        let mut style: egui::Style = ui.style().as_ref().clone();
+                        for (_ts, font) in style.text_styles.iter_mut() {
+                            font.size *= vscale;
+                        }
+                        style.spacing.item_spacing *= vscale;
+                        style.spacing.button_padding *= vscale;
+                        style.spacing.indent *= vscale;
+                        style.spacing.window_margin = style.spacing.window_margin * vscale;
+                        ui.set_style(style);
+                        self.return_flow.show_content(ui, api_client);
+                    });
+                } else {
+                    self.return_flow.show_content(ui, api_client);
+                }
+            } else {
+                self.show_dashboard_grid(ui, row_height, show_full_ui_requested, user, config, api_client);
+            }
+        });
+    }
+
+    fn show_dashboard_grid(
+        &mut self,
+        ui: &mut egui::Ui,
+        row_height: f32,
+        show_full_ui_requested: &mut bool,
+        user: &UserInfo,
+        config: &KioskUiSettings,
+        api_client: &ApiClient,
+    ) {
+        let width = ui.available_width();
+
+        // Dashboard grid headings/buttons use base sizes scaled by global DPI
+        let text_scale = ui.ctx().pixels_per_point();
+        let base_font_size = 14.0 * text_scale;
+        let heading_size = 24.0 * text_scale;
+
+        // --- Row 2: Borrowing ---
+        ui.allocate_ui(egui::vec2(width, row_height), |ui| {
+            ui.vertical(|ui| {
+                ui.with_layout(egui::Layout::top_down(egui::Align::Center), |ui| {
+                    ui.heading(egui::RichText::new("Borrowing").size(heading_size));
+                    ui.add_space(10.0);
+                });
+                
+                ui.horizontal(|ui| {
+                    let num_buttons = 3.0;
+                    let spacing = ui.spacing().item_spacing.x;
+                    let total_spacing = spacing * (num_buttons - 1.0);
+                    let btn_width = (width - total_spacing - 20.0) / num_buttons;
+                    let btn_size = egui::vec2(btn_width, row_height - 80.0);
+                    
+                    // Center buttons horizontally
+                    let total_width = btn_width * num_buttons + total_spacing;
+                    let margin = (width - total_width) / 2.0;
+                    if margin > 0.0 { ui.add_space(margin); }
+                    
+                    if ui.add_sized(btn_size, egui::Button::new(egui::RichText::new("Check Out").size(base_font_size))).clicked() {
+                        self.borrow_flow.open(api_client);
+                    }
+                    
+                    if ui.add_sized(btn_size, egui::Button::new(egui::RichText::new("Check In").size(base_font_size))).clicked() {
+                        self.return_flow.open(api_client);
+                    }
+                    ui.add_sized(btn_size, egui::Button::new(egui::RichText::new("Manage").size(base_font_size)));
+                });
+            });
+        });
+
+        ui.separator();
+
+        // --- Row 3: Inventory ---
+        ui.allocate_ui(egui::vec2(width, row_height), |ui| {
+            ui.vertical(|ui| {
+                ui.with_layout(egui::Layout::top_down(egui::Align::Center), |ui| {
+                    ui.heading(egui::RichText::new("Inventory").size(heading_size));
+                    ui.add_space(10.0);
+                });
+                
+                ui.horizontal(|ui| {
+                    let num_buttons = if user.power >= config.minimum_power_level_for_full_ui { 5.0 } else { 4.0 };
+                    let spacing = ui.spacing().item_spacing.x;
+                    let total_spacing = spacing * (num_buttons - 1.0);
+                    let btn_width = (width - total_spacing - 20.0) / num_buttons;
+                    let btn_size = egui::vec2(btn_width, row_height - 80.0);
+                    
+                    // Center buttons horizontally
+                    let total_width = btn_width * num_buttons + total_spacing;
+                    let margin = (width - total_width) / 2.0;
+                    if margin > 0.0 { ui.add_space(margin); }
+                    
+                    ui.add_sized(btn_size, egui::Button::new(egui::RichText::new("Add").size(base_font_size)));
+                    ui.add_sized(btn_size, egui::Button::new(egui::RichText::new("Move").size(base_font_size)));
+                    ui.add_sized(btn_size, egui::Button::new(egui::RichText::new("See").size(base_font_size)));
+                    ui.add_sized(btn_size, egui::Button::new(egui::RichText::new("Print Label").size(base_font_size)));
+
+                    if user.power >= config.minimum_power_level_for_full_ui {
+                        if ui.add_sized(btn_size, egui::Button::new(egui::RichText::new("Show Full UI").size(base_font_size))).clicked() {
+                            *show_full_ui_requested = true;
+                        }
+                    }
+                });
+            });
+        });
+
+        ui.separator();
+
+        // --- Row 4: Blank ---
+        ui.allocate_ui(egui::vec2(width, row_height), |_ui| {
+           // Blank
+        });
+    }
+}