using CommunityToolkit.Mvvm.ComponentModel; using Livia.Utility; namespace Livia.ViewModels; public interface IPagingControlRecipient { public Task Refresh(); } public class PagingControlViewModel : ObservableObject { public int Offset => (CurrentPage - 1) * ItemPerPage; public int PageCount { get => _pageCount; private set => SetProperty(ref _pageCount, value); } public int TotalCount { get => _totalCount; private set => SetProperty(ref _totalCount, value); } //TODO::Bind to string instead. Currently empty space will trigger error. public int CurrentPage { get => _currentPage; set { int newValue = Math.Clamp(value, 1, PageCount); SetProperty(ref _currentPage, newValue); } } public bool Processing { get => _processing; private set => SetProperty(ref _processing, value); } private bool _processing; private int _pageCount = 1; private int _totalCount; private int _currentPage = 1; private IPagingControlRecipient? _recipient; private readonly DebounceHelper _updateServerJobListBounceHelper = new(TimeSpan.FromSeconds(0.5)); //default to 8 public const int ItemPerPage = 8; public void SetRecipient(IPagingControlRecipient recipient) { _recipient = recipient; } public void SetItemNumber(int n) { PageCount = Math.Max(1, 1 + (n - 1) / ItemPerPage); TotalCount = n; } private async Task TryJumpTo(int n) { if (!_updateServerJobListBounceHelper.TryFire()) return; Processing = true; int oldValue = CurrentPage; CurrentPage = n; if (_recipient != null && !await _recipient.Refresh().ConfigureAwait(false)) { CurrentPage = oldValue; } Processing = false; } public Task First() { return TryJumpTo(1); } public Task Previous() { return TryJumpTo(CurrentPage - 1); } public Task Next() { return TryJumpTo(CurrentPage + 1); } public Task Last() { return TryJumpTo(PageCount); } public Task Refresh() { return TryJumpTo(CurrentPage); } public void RefreshCurrentPage() { int deletePageCount = TotalCount - 1; // delete after page count int maxPage = Math.Max(1, 1 + (deletePageCount - 1) / ItemPerPage); // delete after max page if (this.CurrentPage > maxPage) { this.CurrentPage = maxPage; } } }