216 lines
7.2 KiB
C#
216 lines
7.2 KiB
C#
using System.ComponentModel;
|
||
using System.Diagnostics;
|
||
using System.Runtime.CompilerServices;
|
||
using System.Windows.Input;
|
||
using CORP_MAUI.Models;
|
||
using CORP_MAUI.Pages;
|
||
using CORP_MAUI.Services;
|
||
|
||
namespace CORP_MAUI.ViewModels;
|
||
|
||
public class ProfileViewModel : INotifyPropertyChanged
|
||
{
|
||
private User? _user;
|
||
private bool _isLoading;
|
||
private string? _localImagePath;
|
||
|
||
public ProfileViewModel()
|
||
{
|
||
LoadProfileCommand = new Command(async () => await LoadProfileAsync());
|
||
LogoutCommand = new Command(async () => await LogoutAsync());
|
||
}
|
||
|
||
public User? User
|
||
{
|
||
get => _user;
|
||
set
|
||
{
|
||
_user = value;
|
||
OnPropertyChanged();
|
||
OnPropertyChanged(nameof(FullName));
|
||
OnPropertyChanged(nameof(Username));
|
||
OnPropertyChanged(nameof(Email));
|
||
OnPropertyChanged(nameof(Position));
|
||
OnPropertyChanged(nameof(Department));
|
||
OnPropertyChanged(nameof(StatusText));
|
||
OnPropertyChanged(nameof(StatusColor));
|
||
OnPropertyChanged(nameof(Skills));
|
||
OnPropertyChanged(nameof(HasSkills));
|
||
}
|
||
}
|
||
|
||
public bool IsLoading
|
||
{
|
||
get => _isLoading;
|
||
set
|
||
{
|
||
_isLoading = value;
|
||
OnPropertyChanged();
|
||
}
|
||
}
|
||
|
||
// Wrappers for UI binding
|
||
public string FullName => _user?.FullName ?? "Загрузка...";
|
||
public string Username => _user != null ? $"@{_user.Username}" : "";
|
||
public string Email => _user?.Email ?? "-";
|
||
public string Position => _user?.PositionName ?? "-";
|
||
public string Department => _user?.DepartmentName ?? "-";
|
||
public bool IsOnline => _user?.IsOnline ?? false;
|
||
public string StatusText => IsOnline ? "В сети" : "Не в сети";
|
||
public Color StatusColor => IsOnline ? Colors.LimeGreen : Colors.Gray;
|
||
public List<Skill> Skills => _user?.Skills ?? new List<Skill>();
|
||
public bool HasSkills => Skills.Any();
|
||
|
||
// Image Logic
|
||
public ImageSource? DisplayImageSource
|
||
{
|
||
get
|
||
{
|
||
if (!string.IsNullOrEmpty(_localImagePath) && File.Exists(_localImagePath))
|
||
{
|
||
try
|
||
{
|
||
if (new FileInfo(_localImagePath).Length == 0) return null;
|
||
return ImageSource.FromStream(() =>
|
||
{
|
||
try
|
||
{
|
||
return new FileStream(_localImagePath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||
}
|
||
catch
|
||
{
|
||
return null;
|
||
}
|
||
});
|
||
}
|
||
catch { return null; }
|
||
}
|
||
// Default placeholder if needed
|
||
return ImageSource.FromFile("dotnet_bot.png");
|
||
}
|
||
}
|
||
|
||
public ICommand LoadProfileCommand { get; }
|
||
public ICommand LogoutCommand { get; }
|
||
|
||
public async Task LoadProfileAsync()
|
||
{
|
||
if (IsLoading) return;
|
||
IsLoading = true;
|
||
|
||
try
|
||
{
|
||
User? loadedUser = await ServiceProvider.ApiService.GetCurrentUserAsync();
|
||
if (loadedUser != null)
|
||
{
|
||
User = loadedUser;
|
||
await LoadAvatarAsync();
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Trace.WriteLine($"Error loading profile: {ex.Message}");
|
||
|
||
Page? mainPage = Application.Current?.Windows.FirstOrDefault()?.Page;
|
||
if (mainPage != null)
|
||
await mainPage.DisplayAlert("Ошибка", "Не удалось загрузить профиль", "OK");
|
||
}
|
||
finally
|
||
{
|
||
IsLoading = false;
|
||
}
|
||
}
|
||
|
||
private async Task LoadAvatarAsync()
|
||
{
|
||
if (_user == null || string.IsNullOrEmpty(_user.DisplayAvatarUrl)) return;
|
||
|
||
try
|
||
{
|
||
string url = _user.DisplayAvatarUrl;
|
||
// Generate cache filename
|
||
Uri uri = new Uri(url);
|
||
string extension = Path.GetExtension(uri.LocalPath);
|
||
if (string.IsNullOrEmpty(extension)) extension = ".jpg";
|
||
|
||
string fileName = Path.GetFileNameWithoutExtension(uri.LocalPath);
|
||
fileName = Path.GetInvalidFileNameChars().Aggregate(fileName, (current, c) => current.Replace(c, '_'));
|
||
|
||
string cacheFileName = $"user_{_user.Id}_{fileName}{extension}";
|
||
string cacheFilePath = Path.Combine(FileSystem.CacheDirectory, cacheFileName);
|
||
|
||
// Check cache
|
||
if (File.Exists(cacheFilePath))
|
||
{
|
||
FileInfo fileInfo = new FileInfo(cacheFilePath);
|
||
if (fileInfo.Length > 0)
|
||
{
|
||
_localImagePath = cacheFilePath;
|
||
OnPropertyChanged(nameof(DisplayImageSource));
|
||
return;
|
||
}
|
||
}
|
||
|
||
// Download
|
||
byte[]? bytes = await ServiceProvider.ApiService.GetImageBytesAsync(url);
|
||
if (bytes is { Length: > 0 })
|
||
{
|
||
// Simple signature check
|
||
bool isImage = false;
|
||
if (bytes.Length > 2)
|
||
{
|
||
if (bytes[0] == 0xFF && bytes[1] == 0xD8) isImage = true;
|
||
else if (bytes[0] == 0x89 && bytes[1] == 0x50) isImage = true;
|
||
else isImage = true; // Relaxed check
|
||
|
||
if (bytes[0] == '<') isImage = false; // HTML check
|
||
}
|
||
|
||
if (isImage)
|
||
{
|
||
await File.WriteAllBytesAsync(cacheFilePath, bytes);
|
||
_localImagePath = cacheFilePath;
|
||
OnPropertyChanged(nameof(DisplayImageSource));
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Trace.WriteLine($"Avatar load error: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
private async Task LogoutAsync()
|
||
{
|
||
Page? mainPage = Application.Current?.Windows.FirstOrDefault()?.Page;
|
||
if (mainPage == null) return;
|
||
|
||
bool result = await mainPage.DisplayAlert("Выход", "Вы уверены, что хотите выйти?", "Да", "Нет");
|
||
if (result)
|
||
{
|
||
try
|
||
{
|
||
await ServiceProvider.ApiService.UpdateStatusAsync(false);
|
||
await ServiceProvider.WebSocketService.DisconnectAsync();
|
||
ServiceProvider.ApiService.Logout();
|
||
SecureStorage.Remove("user_id");
|
||
SecureStorage.Remove("username");
|
||
|
||
if (Application.Current?.Windows.Count > 0)
|
||
{
|
||
Application.Current.Windows[0].Page = new NavigationPage(new LoginPage());
|
||
}
|
||
}
|
||
catch(Exception ex)
|
||
{
|
||
await mainPage.DisplayAlert("Ошибка", $"Ошибка при выходе: {ex.Message}", "OK");
|
||
}
|
||
}
|
||
}
|
||
|
||
public event PropertyChangedEventHandler? PropertyChanged;
|
||
protected void OnPropertyChanged([CallerMemberName] string? name = null) =>
|
||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
|
||
}
|
||
|