167 lines
7.3 KiB
C#
167 lines
7.3 KiB
C#
using System.Diagnostics;
|
||
using CORP_MAUI.Pages;
|
||
|
||
namespace CORP_MAUI;
|
||
|
||
public partial class AppShell : Shell
|
||
{
|
||
// Порог ширины для переключения на вертикальное меню (в пикселях)
|
||
private const double WideScreenThreshold = 768;
|
||
|
||
public AppShell()
|
||
{
|
||
try
|
||
{
|
||
Trace.WriteLine("=== APPSHELL CONSTRUCTOR START ===");
|
||
Trace.WriteLine("[AppShell] >>> Вызов InitializeComponent");
|
||
|
||
InitializeComponent();
|
||
|
||
Trace.WriteLine("[AppShell] >>> InitializeComponent завершен");
|
||
Trace.WriteLine("[AppShell] >>> Регистрация маршрутов");
|
||
|
||
// Регистрация маршрутов для навигации
|
||
Routing.RegisterRoute(nameof(ChatPage), typeof(ChatPage));
|
||
Routing.RegisterRoute(nameof(DepartmentDetailsPage), typeof(DepartmentDetailsPage));
|
||
Routing.RegisterRoute(nameof(EmployeeProfilePage), typeof(EmployeeProfilePage));
|
||
|
||
Trace.WriteLine("[AppShell] ✅ AppShell инициализирован");
|
||
Trace.WriteLine("=== APPSHELL CONSTRUCTOR END ===");
|
||
|
||
// Устанавливаем начальный режим меню
|
||
UpdateFlyoutBehavior();
|
||
|
||
// Инициализация без ожидания (так await нельзя из синхронного конструктора)
|
||
_ = InitializeAsync();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Trace.WriteLine("=== APPSHELL CONSTRUCTOR ERROR ===");
|
||
Trace.WriteLine($"[AppShell] ❌ Тип ошибки: {ex.GetType().FullName}");
|
||
Trace.WriteLine($"[AppShell] ❌ Сообщение: {ex.Message}");
|
||
Trace.WriteLine($"[AppShell] ❌ StackTrace: {ex.StackTrace}");
|
||
if (ex.InnerException != null)
|
||
{
|
||
Trace.WriteLine($"[AppShell] ❌ InnerException: {ex.InnerException.Message}");
|
||
Trace.WriteLine($"[AppShell] ❌ InnerException StackTrace: {ex.InnerException.StackTrace}");
|
||
}
|
||
|
||
// Показываем ошибку в диалоге
|
||
Task.Run(async () =>
|
||
{
|
||
await Task.Delay(100);
|
||
await MainThread.InvokeOnMainThreadAsync(async () =>
|
||
{
|
||
Page? mainPage = Application.Current?.Windows.FirstOrDefault()?.Page;
|
||
if (mainPage != null)
|
||
{
|
||
await mainPage.DisplayAlert("Ошибка AppShell",
|
||
$"Ошибка инициализации AppShell:\n{ex.Message}\n\nStackTrace:\n{ex.StackTrace}", "OK");
|
||
}
|
||
});
|
||
});
|
||
|
||
throw;
|
||
}
|
||
}
|
||
|
||
private async Task InitializeAsync()
|
||
{
|
||
try
|
||
{
|
||
Trace.WriteLine("[AppShell] >>> Начало InitializeAsync");
|
||
|
||
// Инициализация сервисов (если они не инициализированы)
|
||
ServiceProvider.Initialize();
|
||
|
||
Trace.WriteLine($"[AppShell] IsAuthenticated: {ServiceProvider.ApiService.IsAuthenticated}");
|
||
|
||
// Проверяем, авторизован ли пользователь (токены загружаются автоматически в ApiService)
|
||
if (ServiceProvider.ApiService.IsAuthenticated)
|
||
{
|
||
// Получаем токен для WebSocket
|
||
string? accessToken = await SecureStorage.GetAsync("api.jwt_access");
|
||
|
||
Trace.WriteLine($"[AppShell] Access token exists: {!string.IsNullOrEmpty(accessToken)}");
|
||
Trace.WriteLine($"[AppShell] WebSocket connected: {ServiceProvider.WebSocketService.IsConnected}");
|
||
|
||
if (!string.IsNullOrEmpty(accessToken) && !ServiceProvider.WebSocketService.IsConnected)
|
||
{
|
||
Trace.WriteLine("[AppShell] >>> Подключение WebSocket из AppShell");
|
||
// Подключаем WebSocket только если его еще не подключен
|
||
await ServiceProvider.WebSocketService.ConnectAsync(accessToken);
|
||
Trace.WriteLine("[AppShell] ✅ WebSocket подключен из AppShell");
|
||
}
|
||
else if (ServiceProvider.WebSocketService.IsConnected)
|
||
{
|
||
Trace.WriteLine("[AppShell] WebSocket уже подключен, пропускаем");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Trace.WriteLine("[AppShell] ⚠️ Пользователь не авторизован");
|
||
}
|
||
|
||
Trace.WriteLine("[AppShell] ✅ InitializeAsync завершен");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Trace.WriteLine($"[AppShell] ❌ Ошибка InitializeAsync: {ex.Message}");
|
||
Trace.WriteLine($"[AppShell] StackTrace: {ex.StackTrace}");
|
||
|
||
await DisplayAlert("Ошибка", $"Ошибка инициализации: {ex.Message}", "OK");
|
||
}
|
||
}
|
||
|
||
protected override void OnSizeAllocated(double width, double height)
|
||
{
|
||
base.OnSizeAllocated(width, height);
|
||
UpdateFlyoutBehavior(width);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Обновляет режим меню в зависимости от ширины экрана
|
||
/// </summary>
|
||
private void UpdateFlyoutBehavior(double? width = null)
|
||
{
|
||
try
|
||
{
|
||
// Получаем текущую ширину окна
|
||
double currentWidth = width ?? (Application.Current?.Windows.FirstOrDefault()?.Width ?? 0);
|
||
|
||
if (currentWidth <= 0)
|
||
{
|
||
// Если ширина не определена, используем DeviceDisplay
|
||
currentWidth = DeviceDisplay.MainDisplayInfo.Width / DeviceDisplay.MainDisplayInfo.Density;
|
||
}
|
||
|
||
Trace.WriteLine($"[AppShell] UpdateFlyoutBehavior: width={currentWidth}, threshold={WideScreenThreshold}");
|
||
|
||
if (currentWidth >= WideScreenThreshold)
|
||
{
|
||
// Широкий экран - Flyout всегда открыт (Locked)
|
||
if (FlyoutBehavior != FlyoutBehavior.Locked)
|
||
{
|
||
FlyoutBehavior = FlyoutBehavior.Locked;
|
||
FlyoutIsPresented = true;
|
||
Trace.WriteLine("[AppShell] ✅ Режим: Locked (вертикальное меню слева)");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// Узкий экран - Flyout выдвигается по кнопке/свайпу
|
||
if (FlyoutBehavior != FlyoutBehavior.Flyout)
|
||
{
|
||
FlyoutBehavior = FlyoutBehavior.Flyout;
|
||
FlyoutIsPresented = false;
|
||
Trace.WriteLine("[AppShell] ✅ Режим: Flyout (выдвижное меню)");
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Trace.WriteLine($"[AppShell] ⚠️ Ошибка UpdateFlyoutBehavior: {ex.Message}");
|
||
}
|
||
}
|
||
}
|