using System.Diagnostics; using FrymasterBadgeApp.Services; using Microsoft.Maui.Storage; namespace FrymasterBadgeApp; public partial class AppShell : Shell { private readonly SqlService _db; private readonly PrinterService _printerService; private readonly IServiceProvider _serviceProvider; private bool _isInitialized = false; /// /// AppShell is a class that contains the initialization code for the app. It is responsible for /// loading all companies in the background and then switching to the main thread to /// update the UI. /// public AppShell(SqlService db, PrinterService printerService, IServiceProvider serviceProvider) { InitializeComponent(); _db = db; _printerService = printerService; _serviceProvider = serviceProvider; // Register pages that are NOT part of the TabBar permanently Routing.RegisterRoute(nameof(SettingsPage), typeof(SettingsPage)); Routing.RegisterRoute(nameof(CompanyPage), typeof(CompanyPage)); Routing.RegisterRoute(nameof(EmployeePage), typeof(EmployeePage)); } protected override async void OnAppearing() { base.OnAppearing(); // Using a small delay or ensuring initialization happens once if (!_isInitialized) { _isInitialized = true; await LoadCompaniesAsync(); } } /// /// Loads all companies in the background and then switches to the main thread to update the UI. /// private async Task LoadCompaniesAsync() { try { // 1. Fetch data in background AppLogger.Debug("AppShell: Fetching companies"); var companies = await Task.Run(() => _db.Query("SELECT * FROM dbo.Companies", null)); // 2. Switch to Main Thread for UI changes await MainThread.InvokeOnMainThreadAsync(async () => { // Clear the "Loading" item MainTabBar.Items.Clear(); if (companies == null || !companies.Any()) { MainTabBar.Items.Add( new ShellContent { Title = "Setup", Route = "InitialSetup", ContentTemplate = new DataTemplate(() => _serviceProvider.GetRequiredService() ), } ); } else { foreach (var company in companies) { var companyId = company.GetValueOrDefault("ID")?.ToString() ?? "0"; MainTabBar.Items.Add( new ShellContent { Title = company.GetValueOrDefault("Name")?.ToString() ?? "Unknown", Route = $"EmployeePage_{companyId}", ContentTemplate = new DataTemplate(() => new EmployeePage(_db, _printerService, company) ), } ); } } // 3. Navigate away from the Loading page to the first real tab if (MainTabBar.Items.Count > 0) { var targetRoute = MainTabBar.Items[0].Route; // The "///" is critical—it tells Shell to rebuild the navigation stack await Shell.Current.GoToAsync($"///{targetRoute}"); } }); } catch (Exception ex) { AppLogger.Error("AppShell: Error loading companies", ex); // Fallback: If DB fails, at least show the Company page await Shell.Current.GoToAsync($"///InitialSetup"); } } /// /// Navigates to CompanyPage as a sub-page (pushed onto the stack). public async void OnManageCompaniesClicked(object sender, EventArgs e) { // Navigates to CompanyPage as a sub-page (pushed onto the stack) await Shell.Current.GoToAsync(nameof(CompanyPage)); } private async void OnSettingsClicked(object sender, EventArgs e) => await Shell.Current.GoToAsync(nameof(SettingsPage)); /// /// Open a simple action sheet to choose theme globally /// /// The object that triggered the event /// The event arguments private async void OnThemeClicked(object sender, EventArgs e) { // Open a simple action sheet to choose theme globally string action = await Shell.Current.DisplayActionSheet("Select Theme", "Cancel", null, "System", "Light", "Dark"); if (action == "Cancel" || string.IsNullOrEmpty(action)) return; switch (action) { case "Light": Application.Current.UserAppTheme = AppTheme.Light; Preferences.Default.Set("AppTheme", "Light"); break; case "Dark": Application.Current.UserAppTheme = AppTheme.Dark; Preferences.Default.Set("AppTheme", "Dark"); break; default: Application.Current.UserAppTheme = AppTheme.Unspecified; Preferences.Default.Set("AppTheme", "System"); break; } } private void OnExitClicked(object sender, EventArgs e) => Application.Current?.Quit(); /// /// Open a simple action sheet to show the app's about page /// /// The object that triggered the event /// The event arguments private async void OnAboutClicked(object sender, EventArgs e) => await DisplayAlert("About", "Frymaster Badge App v1.0", "OK"); }