corp-app/CORP-MAUI/Pages/PostsPage.xaml.cs

168 lines
6.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Collections.ObjectModel;
using System.Diagnostics;
using CORP_MAUI.ViewModels;
namespace CORP_MAUI.Pages;
public partial class PostsPage
{
private readonly ObservableCollection<PostViewModel> _posts;
private int _currentPage = 1;
private bool _isLoading;
public PostsPage()
{
InitializeComponent();
_posts = new ObservableCollection<PostViewModel>();
PostsCollectionView.ItemsSource = _posts;
}
// Добавляем метод OnAppearing, чтобы обновлять данные при показе страницы, если нужно
protected override void OnAppearing()
{
base.OnAppearing();
if (_posts.Count == 0)
{
_ = LoadPostsAsync();
}
}
private async Task LoadPostsAsync(bool refresh = false)
{
if (_isLoading) return;
_isLoading = true;
if (refresh)
{
_currentPage = 1;
}
try
{
LoadingIndicator.IsVisible = true;
LoadingIndicator.IsRunning = true;
var response = await ServiceProvider.ApiService.GetPostsPaginatedAsync(_currentPage);
if (refresh)
{
_posts.Clear();
}
if (response.Results != null)
{
foreach (var post in response.Results)
{
Trace.WriteLine($"[PostsPage] Post {post.Id}: '{post.Title}'");
Trace.WriteLine($" CreatedAt: {post.CreatedAt}");
Trace.WriteLine($" DisplayImageUrl: {post.DisplayImageUrl}");
Trace.WriteLine($" Content length: {post.Content?.Length ?? 0}");
var vm = new PostViewModel(post);
_posts.Add(vm);
// Асинхронно загружаем изображение с токеном
_ = Task.Run(async () =>
{
if (!string.IsNullOrEmpty(post.DisplayImageUrl))
{
try
{
// Используем имя файла из URL как ключ кэша
var uri = new Uri(post.DisplayImageUrl);
var fileName = Path.GetFileName(uri.LocalPath);
// Добавляем префикс, чтобы избежать коллизий
var cacheFileName = $"cache_{post.Id}_{fileName}";
var cacheFilePath = Path.Combine(FileSystem.CacheDirectory, cacheFileName);
// Проверяем кэш
if (File.Exists(cacheFilePath))
{
var fileInfo = new FileInfo(cacheFilePath);
if (fileInfo.Length > 0)
{
Trace.WriteLine($"[PostsPage] >> Image found in cache: {cacheFilePath}");
await MainThread.InvokeOnMainThreadAsync(() =>
{
vm.LocalImagePath = cacheFilePath;
});
return;
}
else
{
// Удаляем пустой файл
File.Delete(cacheFilePath);
}
}
// Загружаем, если нет в кэше
var bytes = await ServiceProvider.ApiService.GetImageBytesAsync(post.DisplayImageUrl);
if (bytes != null && bytes.Length > 0)
{
Trace.WriteLine($"[PostsPage] >> Image loaded ({bytes.Length} bytes), saving to {cacheFilePath}");
// Сразу показываем
await MainThread.InvokeOnMainThreadAsync(() =>
{
vm.AuthorizedImageSource = ImageSource.FromStream(() => new MemoryStream(bytes));
});
await File.WriteAllBytesAsync(cacheFilePath, bytes);
// Обновляем путь (на всякий случай, для будущего)
await MainThread.InvokeOnMainThreadAsync(() =>
{
vm.LocalImagePath = cacheFilePath;
});
}
else
{
Trace.WriteLine($"[PostsPage] >> Image failed to load for post {post.Id} (null/empty)");
}
}
catch(Exception imgEx)
{
Trace.WriteLine($"[PostsPage] >> Exception loading image for post {post.Id}: {imgEx.Message}");
}
}
else
{
Trace.WriteLine($"[PostsPage] >> No image URL for post {post.Id}");
}
});
}
}
}
catch (Exception ex)
{
Trace.WriteLine($"Ошибка загрузки постов: {ex.Message}");
await DisplayAlert("Ошибка", "Не удалось загрузить новости", "OK");
}
finally
{
_isLoading = false;
LoadingIndicator.IsVisible = false;
LoadingIndicator.IsRunning = false;
PostsRefreshView.IsRefreshing = false;
}
}
private async void OnRefreshing(object sender, EventArgs e)
{
await LoadPostsAsync(true);
}
private async void OnPostSelected(object sender, SelectionChangedEventArgs e)
{
if (e.CurrentSelection.FirstOrDefault() is PostViewModel selectedPost)
{
// Навигация на страницу деталей
await Navigation.PushAsync(new PostDetailsPage(selectedPost));
// Снимаем выделение
PostsCollectionView.SelectedItem = null;
}
}
}