using OF_DL.Models.Downloads; using OF_DL.Services; namespace OF_DL.Gui.Services; internal sealed class AvaloniaDownloadEventHandler( Action activitySink, Action progressStatusUpdate, Action progressStart, Action progressIncrement, Action progressStop, Func isCancellationRequested) : IDownloadEventHandler { public async Task WithStatusAsync(string statusMessage, Func> work) { ThrowIfCancellationRequested(); progressStart(statusMessage, 0, false); try { AvaloniaStatusReporter statusReporter = new(progressStatusUpdate, isCancellationRequested); return await work(statusReporter); } finally { progressStop(); } } public async Task WithProgressAsync(string description, long maxValue, bool showSize, Func> work) { ThrowIfCancellationRequested(); progressStart(description, maxValue, showSize); try { AvaloniaProgressReporter reporter = new(progressIncrement, isCancellationRequested); return await work(reporter); } finally { progressStop(); } } public void OnContentFound(string contentType, int mediaCount, int objectCount) { ThrowIfCancellationRequested(); progressStatusUpdate($"Found {mediaCount} media from {objectCount} {contentType}."); } public void OnNoContentFound(string contentType) { ThrowIfCancellationRequested(); progressStatusUpdate($"Found 0 {contentType}."); } public void OnDownloadComplete(string contentType, DownloadResult result) { ThrowIfCancellationRequested(); progressStatusUpdate( $"{contentType} complete. Existing: {result.ExistingDownloads}, New: {result.NewDownloads}, Total: {result.TotalCount}."); } public void OnUserStarting(string username) { ThrowIfCancellationRequested(); activitySink($"Starting scrape for {username}."); progressStatusUpdate($"Scraping data for {username}..."); } public void OnUserComplete(string username, CreatorDownloadResult result) { ThrowIfCancellationRequested(); activitySink( $"Completed {username}. PaidPosts={result.PaidPostCount}, Posts={result.PostCount}, Archived={result.ArchivedCount}, Streams={result.StreamsCount}, Stories={result.StoriesCount}, Highlights={result.HighlightsCount}, Messages={result.MessagesCount}, PaidMessages={result.PaidMessagesCount}."); } public void OnPurchasedTabUserComplete(string username, int paidPostCount, int paidMessagesCount) { ThrowIfCancellationRequested(); activitySink($"Purchased tab complete for {username}. PaidPosts={paidPostCount}, PaidMessages={paidMessagesCount}."); } public void OnScrapeComplete(TimeSpan elapsed) { ThrowIfCancellationRequested(); activitySink($"Scrape completed in {elapsed.TotalMinutes:0.00} minutes."); } public void OnMessage(string message) { ThrowIfCancellationRequested(); progressStatusUpdate(message); } private void ThrowIfCancellationRequested() { if (isCancellationRequested()) { throw new OperationCanceledException("Operation canceled by user."); } } }