FrymasterBadgeApp/AppShell.xaml.cs

159 lines
5.9 KiB
C#

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;
/// <summary>
/// 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.
/// </summary>
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();
}
}
/// <summary>
/// Loads all companies in the background and then switches to the main thread to update the UI.
/// </summary>
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<CompanyPage>()
),
}
);
}
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");
}
}
/// <summary>
/// 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));
/// <summary>
/// Open a simple action sheet to choose theme globally
/// </summary>
/// <param name="sender">The object that triggered the event</param>
/// <param name="e">The event arguments</param>
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();
/// <summary>
/// Open a simple action sheet to show the app's about page
/// </summary>
/// <param name="sender">The object that triggered the event</param>
/// <param name="e">The event arguments</param>
private async void OnAboutClicked(object sender, EventArgs e) =>
await DisplayAlert("About", "Frymaster Badge App v1.0", "OK");
}