Move ProcessQueue biz logic into viewmodel
This commit is contained in:
parent
3a61c32881
commit
c727286d22
BIN
Source/LibationWinForms/AvaloniaUI/Assets/glass-with-glow_16.png
Normal file
BIN
Source/LibationWinForms/AvaloniaUI/Assets/glass-with-glow_16.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 482 B |
@ -1,14 +0,0 @@
|
|||||||
using Dinah.Core.Threading;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
namespace LibationWinForms.AvaloniaUI
|
|
||||||
{
|
|
||||||
public abstract class AsyncNotifyPropertyChanged2 : INotifyPropertyChanged
|
|
||||||
{
|
|
||||||
// see also notes in Libation/Source/_ARCHITECTURE NOTES.txt :: MVVM
|
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
|
||||||
public void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
|
|
||||||
=> Avalonia.Threading.Dispatcher.UIThread.Post(() => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,15 +1,10 @@
|
|||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace LibationWinForms.AvaloniaUI
|
namespace LibationWinForms.AvaloniaUI
|
||||||
{
|
{
|
||||||
internal static class AvaloniaUtils
|
internal static class AvaloniaUtils
|
||||||
{
|
{
|
||||||
|
|
||||||
public static IBrush GetBrushFromResources(string name)
|
public static IBrush GetBrushFromResources(string name)
|
||||||
=> GetBrushFromResources(name, Brushes.Transparent);
|
=> GetBrushFromResources(name, Brushes.Transparent);
|
||||||
public static IBrush GetBrushFromResources(string name, IBrush defaultBrush)
|
public static IBrush GetBrushFromResources(string name, IBrush defaultBrush)
|
||||||
|
|||||||
@ -1,7 +1,11 @@
|
|||||||
using Avalonia.Threading;
|
using ApplicationServices;
|
||||||
|
using Avalonia.Threading;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace LibationWinForms.AvaloniaUI.ViewModels
|
namespace LibationWinForms.AvaloniaUI.ViewModels
|
||||||
{
|
{
|
||||||
@ -15,7 +19,52 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
|
|||||||
set => this.RaiseAndSetIfChanged(ref _items, value);
|
set => this.RaiseAndSetIfChanged(ref _items, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TrackedQueue2<ProcessBook2> Queue => Items;
|
||||||
|
|
||||||
public ProcessBook2 SelectedItem { get; set; }
|
public ProcessBook2 SelectedItem { get; set; }
|
||||||
|
public Task QueueRunner { get; private set; }
|
||||||
|
public bool Running => !QueueRunner?.IsCompleted ?? false;
|
||||||
|
|
||||||
|
public ProcessQueueViewModel()
|
||||||
|
{
|
||||||
|
Queue.QueuededCountChanged += Queue_QueuededCountChanged;
|
||||||
|
Queue.CompletedCountChanged += Queue_CompletedCountChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _completedCount;
|
||||||
|
private int _errorCount;
|
||||||
|
private int _queuedCount;
|
||||||
|
private string _runningTime;
|
||||||
|
private bool _progressBarVisible;
|
||||||
|
|
||||||
|
public int CompletedCount { get => _completedCount; private set { this.RaiseAndSetIfChanged(ref _completedCount, value); this.RaisePropertyChanged(nameof(AnyCompleted)); } }
|
||||||
|
public int QueuedCount { get => _queuedCount; private set { this.RaiseAndSetIfChanged(ref _queuedCount, value); this.RaisePropertyChanged(nameof(AnyQueued)); } }
|
||||||
|
public int ErrorCount { get => _errorCount; private set { this.RaiseAndSetIfChanged(ref _errorCount, value); this.RaisePropertyChanged(nameof(AnyErrors)); } }
|
||||||
|
public string RunningTime { get => _runningTime; set { this.RaiseAndSetIfChanged(ref _runningTime, value); } }
|
||||||
|
public bool ProgressBarVisible { get => _progressBarVisible; set { this.RaiseAndSetIfChanged(ref _progressBarVisible, value); } }
|
||||||
|
|
||||||
|
public bool AnyCompleted => CompletedCount > 0;
|
||||||
|
public bool AnyQueued => QueuedCount > 0;
|
||||||
|
public bool AnyErrors => ErrorCount > 0;
|
||||||
|
|
||||||
|
public double Progress => 100d * Queue.Completed.Count / Queue.Count;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void Queue_CompletedCountChanged(object sender, int e)
|
||||||
|
{
|
||||||
|
int errCount = Queue.Completed.Count(p => p.Result is ProcessBookResult.FailedAbort or ProcessBookResult.FailedSkip or ProcessBookResult.FailedRetry or ProcessBookResult.ValidationFail);
|
||||||
|
int completeCount = Queue.Completed.Count(p => p.Result is ProcessBookResult.Success);
|
||||||
|
|
||||||
|
ErrorCount = errCount;
|
||||||
|
CompletedCount = completeCount;
|
||||||
|
this.RaisePropertyChanged(nameof(Progress));
|
||||||
|
}
|
||||||
|
private void Queue_QueuededCountChanged(object sender, int cueCount)
|
||||||
|
{
|
||||||
|
QueuedCount = cueCount;
|
||||||
|
this.RaisePropertyChanged(nameof(Progress));
|
||||||
|
}
|
||||||
|
|
||||||
public void WriteLine(string text)
|
public void WriteLine(string text)
|
||||||
{
|
{
|
||||||
@ -26,6 +75,69 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
|
|||||||
LogMessage = text.Trim()
|
LogMessage = text.Trim()
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AddToQueue(IEnumerable<ProcessBook2> pbook)
|
||||||
|
{
|
||||||
|
Dispatcher.UIThread.Post(() =>
|
||||||
|
{
|
||||||
|
Queue.Enqueue(pbook);
|
||||||
|
if (!Running)
|
||||||
|
QueueRunner = QueueLoop();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime StartingTime;
|
||||||
|
private async Task QueueLoop()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Serilog.Log.Logger.Information("Begin processing queue");
|
||||||
|
|
||||||
|
RunningTime = string.Empty;
|
||||||
|
ProgressBarVisible = true;
|
||||||
|
StartingTime = DateTime.Now;
|
||||||
|
|
||||||
|
using var counterTimer = new System.Threading.Timer(CounterTimer_Tick, null, 0, 500);
|
||||||
|
|
||||||
|
while (Queue.MoveNext())
|
||||||
|
{
|
||||||
|
var nextBook = Queue.Current;
|
||||||
|
|
||||||
|
Serilog.Log.Logger.Information("Begin processing queued item. {item_LibraryBook}", nextBook?.LibraryBook);
|
||||||
|
|
||||||
|
var result = await nextBook.ProcessOneAsync();
|
||||||
|
|
||||||
|
Serilog.Log.Logger.Information("Completed processing queued item: {item_LibraryBook}\r\nResult: {result}", nextBook?.LibraryBook, result);
|
||||||
|
|
||||||
|
if (result == ProcessBookResult.ValidationFail)
|
||||||
|
Queue.ClearCurrent();
|
||||||
|
else if (result == ProcessBookResult.FailedAbort)
|
||||||
|
Queue.ClearQueue();
|
||||||
|
else if (result == ProcessBookResult.FailedSkip)
|
||||||
|
nextBook.LibraryBook.Book.UpdateBookStatus(DataLayer.LiberatedStatus.Error);
|
||||||
|
}
|
||||||
|
Serilog.Log.Logger.Information("Completed processing queue");
|
||||||
|
|
||||||
|
Queue_CompletedCountChanged(this, 0);
|
||||||
|
ProgressBarVisible = false;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Serilog.Log.Logger.Error(ex, "An error was encountered while processing queued items");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CounterTimer_Tick(object? state)
|
||||||
|
{
|
||||||
|
string timeToStr(TimeSpan time)
|
||||||
|
{
|
||||||
|
string minsSecs = $"{time:mm\\:ss}";
|
||||||
|
if (time.TotalHours >= 1)
|
||||||
|
return $"{time.TotalHours:F0}:{minsSecs}";
|
||||||
|
return minsSecs;
|
||||||
|
}
|
||||||
|
RunningTime = timeToStr(DateTime.Now - StartingTime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LogEntry
|
public class LogEntry
|
||||||
|
|||||||
@ -8,7 +8,9 @@
|
|||||||
xmlns:prgid="clr-namespace:LibationWinForms.AvaloniaUI.Views.ProductsGrid"
|
xmlns:prgid="clr-namespace:LibationWinForms.AvaloniaUI.Views.ProductsGrid"
|
||||||
xmlns:controls="clr-namespace:LibationWinForms.AvaloniaUI.Controls"
|
xmlns:controls="clr-namespace:LibationWinForms.AvaloniaUI.Controls"
|
||||||
mc:Ignorable="d" d:DesignWidth="2000" d:DesignHeight="700"
|
mc:Ignorable="d" d:DesignWidth="2000" d:DesignHeight="700"
|
||||||
x:Class="LibationWinForms.AvaloniaUI.Views.MainWindow" Title="MainWindow">
|
x:Class="LibationWinForms.AvaloniaUI.Views.MainWindow"
|
||||||
|
Title="MainWindow"
|
||||||
|
Icon="/AvaloniaUI/Assets/glass-with-glow_16.png">
|
||||||
|
|
||||||
<Border BorderBrush="{DynamicResource DataGridGridLinesBrush}" BorderThickness="2" Padding="15">
|
<Border BorderBrush="{DynamicResource DataGridGridLinesBrush}" BorderThickness="2" Padding="15">
|
||||||
<Grid RowDefinitions="Auto,Auto,*,Auto">
|
<Grid RowDefinitions="Auto,Auto,*,Auto">
|
||||||
|
|||||||
@ -91,24 +91,24 @@
|
|||||||
<Setter Property="MinWidth" Value="100" />
|
<Setter Property="MinWidth" Value="100" />
|
||||||
</Style>
|
</Style>
|
||||||
</Panel.Styles>
|
</Panel.Styles>
|
||||||
<ProgressBar Name="toolStripProgressBar1" ShowProgressText="True" />
|
<ProgressBar IsVisible="{Binding ProgressBarVisible}" Value="{Binding Progress}" ShowProgressText="True" />
|
||||||
</Panel>
|
</Panel>
|
||||||
<StackPanel Orientation="Horizontal" Grid.Column="1">
|
<StackPanel Orientation="Horizontal" Grid.Column="1">
|
||||||
<StackPanel Margin="5,0,0,0" Orientation="Horizontal">
|
<StackPanel Margin="5,0,0,0" Orientation="Horizontal">
|
||||||
<Image Name="queueNumberLbl_Icon" Width="20" Height="20" Source="/AvaloniaUI/Assets/queued.png" />
|
<Image IsVisible="{Binding AnyQueued}" Width="20" Height="20" Source="/AvaloniaUI/Assets/queued.png" />
|
||||||
<TextBlock Name="queueNumberLbl_Text" VerticalAlignment="Center" Text="[Q#]" />
|
<TextBlock IsVisible="{Binding AnyQueued}" VerticalAlignment="Center" Text="{Binding QueuedCount}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<StackPanel Margin="5,0,0,0" Orientation="Horizontal">
|
<StackPanel Margin="5,0,0,0" Orientation="Horizontal">
|
||||||
<Image Name="completedNumberLbl_Icon" Width="20" Height="20" Source="/AvaloniaUI/Assets/completed.png" />
|
<Image IsVisible="{Binding AnyCompleted}" Width="20" Height="20" Source="/AvaloniaUI/Assets/completed.png" />
|
||||||
<TextBlock Name="completedNumberLbl_Text" VerticalAlignment="Center" Text="[DL#]" />
|
<TextBlock IsVisible="{Binding AnyCompleted}" VerticalAlignment="Center" Text="{Binding CompletedCount}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<StackPanel Margin="5,0,0,0" Orientation="Horizontal">
|
<StackPanel Margin="5,0,0,0" Orientation="Horizontal">
|
||||||
<Image Name="errorNumberLbl_Icon" Width="20" Height="20" Source="/AvaloniaUI/Assets/errored.png" />
|
<Image IsVisible="{Binding AnyErrors}" Width="20" Height="20" Source="/AvaloniaUI/Assets/errored.png" />
|
||||||
<TextBlock Name="errorNumberLbl_Text" VerticalAlignment="Center" Text="[ERR#]" />
|
<TextBlock IsVisible="{Binding AnyErrors}" VerticalAlignment="Center" Text="{Binding ErrorCount}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<Panel Grid.Column="2" Margin="0,0,5,0" HorizontalAlignment="Right" VerticalAlignment="Center">
|
<Panel Grid.Column="2" Margin="0,0,5,0" HorizontalAlignment="Right" VerticalAlignment="Center">
|
||||||
<TextBlock Name="runningTimeLbl">00:00:25</TextBlock>
|
<TextBlock Text="{Binding RunningTime}" />
|
||||||
</Panel>
|
</Panel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@ -26,37 +26,7 @@ namespace LibationWinForms.AvaloniaUI.Views
|
|||||||
private TrackedQueue2<ProcessBook2> Queue => _viewModel.Items;
|
private TrackedQueue2<ProcessBook2> Queue => _viewModel.Items;
|
||||||
|
|
||||||
private readonly ProcessQueue.LogMe Logger;
|
private readonly ProcessQueue.LogMe Logger;
|
||||||
private int QueuedCount
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
queueNumberLbl_Text.Text = value.ToString();
|
|
||||||
queueNumberLbl_Text.IsVisible = value > 0;
|
|
||||||
queueNumberLbl_Icon.IsVisible = value > 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private int ErrorCount
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
errorNumberLbl_Text.Text = value.ToString();
|
|
||||||
errorNumberLbl_Text.IsVisible = value > 0;
|
|
||||||
errorNumberLbl_Icon.IsVisible = value > 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int CompletedCount
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
completedNumberLbl_Text.Text = value.ToString();
|
|
||||||
completedNumberLbl_Text.IsVisible = value > 0;
|
|
||||||
completedNumberLbl_Icon.IsVisible = value > 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task QueueRunner { get; private set; }
|
|
||||||
public bool Running => !QueueRunner?.IsCompleted ?? false;
|
|
||||||
|
|
||||||
public ProcessQueueControl2()
|
public ProcessQueueControl2()
|
||||||
{
|
{
|
||||||
@ -71,22 +41,6 @@ namespace LibationWinForms.AvaloniaUI.Views
|
|||||||
ProcessBookControl2.PositionButtonClicked += ProcessBookControl2_ButtonClicked;
|
ProcessBookControl2.PositionButtonClicked += ProcessBookControl2_ButtonClicked;
|
||||||
ProcessBookControl2.CancelButtonClicked += ProcessBookControl2_CancelButtonClicked;
|
ProcessBookControl2.CancelButtonClicked += ProcessBookControl2_CancelButtonClicked;
|
||||||
|
|
||||||
queueNumberLbl_Icon = this.FindControl<Image>(nameof(queueNumberLbl_Icon));
|
|
||||||
errorNumberLbl_Icon = this.FindControl<Image>(nameof(errorNumberLbl_Icon));
|
|
||||||
completedNumberLbl_Icon = this.FindControl<Image>(nameof(completedNumberLbl_Icon));
|
|
||||||
|
|
||||||
queueNumberLbl_Text = this.FindControl<TextBlock>(nameof(queueNumberLbl_Text));
|
|
||||||
errorNumberLbl_Text = this.FindControl<TextBlock>(nameof(errorNumberLbl_Text));
|
|
||||||
completedNumberLbl_Text = this.FindControl<TextBlock>(nameof(completedNumberLbl_Text));
|
|
||||||
|
|
||||||
runningTimeLbl = this.FindControl<TextBlock>(nameof(runningTimeLbl));
|
|
||||||
|
|
||||||
toolStripProgressBar1 = this.FindControl<ProgressBar>(nameof(toolStripProgressBar1));
|
|
||||||
|
|
||||||
|
|
||||||
Queue.QueuededCountChanged += Queue_QueuededCountChanged;
|
|
||||||
Queue.CompletedCountChanged += Queue_CompletedCountChanged;
|
|
||||||
|
|
||||||
#region Design Mode Testing
|
#region Design Mode Testing
|
||||||
if (Design.IsDesignMode)
|
if (Design.IsDesignMode)
|
||||||
{
|
{
|
||||||
@ -140,11 +94,6 @@ namespace LibationWinForms.AvaloniaUI.Views
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
runningTimeLbl.Text = string.Empty;
|
|
||||||
QueuedCount = 0;
|
|
||||||
ErrorCount = 0;
|
|
||||||
CompletedCount = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitializeComponent()
|
private void InitializeComponent()
|
||||||
@ -152,6 +101,72 @@ namespace LibationWinForms.AvaloniaUI.Views
|
|||||||
AvaloniaXamlLoader.Load(this);
|
AvaloniaXamlLoader.Load(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool isBookInQueue(LibraryBook libraryBook)
|
||||||
|
=> Queue.Any(b => b?.LibraryBook?.Book?.AudibleProductId == libraryBook.Book.AudibleProductId);
|
||||||
|
|
||||||
|
public void AddDownloadPdf(LibraryBook libraryBook)
|
||||||
|
=> AddDownloadPdf(new List<LibraryBook>() { libraryBook });
|
||||||
|
|
||||||
|
public void AddDownloadDecrypt(LibraryBook libraryBook)
|
||||||
|
=> AddDownloadDecrypt(new List<LibraryBook>() { libraryBook });
|
||||||
|
|
||||||
|
public void AddConvertMp3(LibraryBook libraryBook)
|
||||||
|
=> AddConvertMp3(new List<LibraryBook>() { libraryBook });
|
||||||
|
|
||||||
|
public void AddDownloadPdf(IEnumerable<LibraryBook> entries)
|
||||||
|
{
|
||||||
|
List<ProcessBook2> procs = new();
|
||||||
|
foreach (var entry in entries)
|
||||||
|
{
|
||||||
|
if (isBookInQueue(entry))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ProcessBook2 pbook = new(entry, Logger);
|
||||||
|
pbook.AddDownloadPdf();
|
||||||
|
procs.Add(pbook);
|
||||||
|
}
|
||||||
|
|
||||||
|
Serilog.Log.Logger.Information("Queueing {count} books", procs.Count);
|
||||||
|
_viewModel.AddToQueue(procs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddDownloadDecrypt(IEnumerable<LibraryBook> entries)
|
||||||
|
{
|
||||||
|
List<ProcessBook2> procs = new();
|
||||||
|
foreach (var entry in entries)
|
||||||
|
{
|
||||||
|
if (isBookInQueue(entry))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ProcessBook2 pbook = new(entry, Logger);
|
||||||
|
pbook.AddDownloadDecryptBook();
|
||||||
|
pbook.AddDownloadPdf();
|
||||||
|
procs.Add(pbook);
|
||||||
|
}
|
||||||
|
|
||||||
|
Serilog.Log.Logger.Information("Queueing {count} books", procs.Count);
|
||||||
|
_viewModel.AddToQueue(procs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddConvertMp3(IEnumerable<LibraryBook> entries)
|
||||||
|
{
|
||||||
|
List<ProcessBook2> procs = new();
|
||||||
|
foreach (var entry in entries)
|
||||||
|
{
|
||||||
|
if (isBookInQueue(entry))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ProcessBook2 pbook = new(entry, Logger);
|
||||||
|
pbook.AddConvertToMp3();
|
||||||
|
procs.Add(pbook);
|
||||||
|
}
|
||||||
|
|
||||||
|
Serilog.Log.Logger.Information("Queueing {count} books", procs.Count);
|
||||||
|
_viewModel.AddToQueue(procs);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Control event handlers
|
||||||
|
|
||||||
private async void ProcessBookControl2_CancelButtonClicked(ProcessBook2 item)
|
private async void ProcessBookControl2_CancelButtonClicked(ProcessBook2 item)
|
||||||
{
|
{
|
||||||
if (item is not null)
|
if (item is not null)
|
||||||
@ -191,8 +206,8 @@ namespace LibationWinForms.AvaloniaUI.Views
|
|||||||
{
|
{
|
||||||
Queue.ClearCompleted();
|
Queue.ClearCompleted();
|
||||||
|
|
||||||
if (!Running)
|
if (!_viewModel.Running)
|
||||||
runningTimeLbl.Text = string.Empty;
|
_viewModel.RunningTime = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClearLogBtn_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
|
public void ClearLogBtn_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
|
||||||
@ -206,139 +221,6 @@ namespace LibationWinForms.AvaloniaUI.Views
|
|||||||
System.Windows.Forms.Clipboard.SetDataObject(logText, false, 5, 150);
|
System.Windows.Forms.Clipboard.SetDataObject(logText, false, 5, 150);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private bool isBookInQueue(LibraryBook libraryBook)
|
|
||||||
=> Queue.Any(b => b?.LibraryBook?.Book?.AudibleProductId == libraryBook.Book.AudibleProductId);
|
|
||||||
|
|
||||||
public void AddDownloadPdf(LibraryBook libraryBook)
|
|
||||||
=> AddDownloadPdf(new List<LibraryBook>() { libraryBook });
|
|
||||||
|
|
||||||
public void AddDownloadDecrypt(LibraryBook libraryBook)
|
|
||||||
=> AddDownloadDecrypt(new List<LibraryBook>() { libraryBook });
|
|
||||||
|
|
||||||
public void AddConvertMp3(LibraryBook libraryBook)
|
|
||||||
=> AddConvertMp3(new List<LibraryBook>() { libraryBook });
|
|
||||||
|
|
||||||
public void AddDownloadPdf(IEnumerable<LibraryBook> entries)
|
|
||||||
{
|
|
||||||
List<ProcessBook2> procs = new();
|
|
||||||
foreach (var entry in entries)
|
|
||||||
{
|
|
||||||
if (isBookInQueue(entry))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
ProcessBook2 pbook = new(entry, Logger);
|
|
||||||
pbook.AddDownloadPdf();
|
|
||||||
procs.Add(pbook);
|
|
||||||
}
|
|
||||||
|
|
||||||
Serilog.Log.Logger.Information("Queueing {count} books", procs.Count);
|
|
||||||
AddToQueue(procs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddDownloadDecrypt(IEnumerable<LibraryBook> entries)
|
|
||||||
{
|
|
||||||
List<ProcessBook2> procs = new();
|
|
||||||
foreach (var entry in entries)
|
|
||||||
{
|
|
||||||
if (isBookInQueue(entry))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
ProcessBook2 pbook = new(entry, Logger);
|
|
||||||
pbook.AddDownloadDecryptBook();
|
|
||||||
pbook.AddDownloadPdf();
|
|
||||||
procs.Add(pbook);
|
|
||||||
}
|
|
||||||
|
|
||||||
Serilog.Log.Logger.Information("Queueing {count} books", procs.Count);
|
|
||||||
AddToQueue(procs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddConvertMp3(IEnumerable<LibraryBook> entries)
|
|
||||||
{
|
|
||||||
List<ProcessBook2> procs = new();
|
|
||||||
foreach (var entry in entries)
|
|
||||||
{
|
|
||||||
if (isBookInQueue(entry))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
ProcessBook2 pbook = new(entry, Logger);
|
|
||||||
pbook.AddConvertToMp3();
|
|
||||||
procs.Add(pbook);
|
|
||||||
}
|
|
||||||
|
|
||||||
Serilog.Log.Logger.Information("Queueing {count} books", procs.Count);
|
|
||||||
AddToQueue(procs);
|
|
||||||
}
|
|
||||||
private void AddToQueue(IEnumerable<ProcessBook2> pbook)
|
|
||||||
{
|
|
||||||
Dispatcher.UIThread.Post(() =>
|
|
||||||
{
|
|
||||||
Queue.Enqueue(pbook);
|
|
||||||
if (!Running)
|
|
||||||
QueueRunner = QueueLoop();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
DateTime StartingTime;
|
|
||||||
private async Task QueueLoop()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Serilog.Log.Logger.Information("Begin processing queue");
|
|
||||||
|
|
||||||
StartingTime = DateTime.Now;
|
|
||||||
|
|
||||||
using var counterTimer = new System.Threading.Timer(CounterTimer_Tick, null, 0, 500);
|
|
||||||
|
|
||||||
while (Queue.MoveNext())
|
|
||||||
{
|
|
||||||
var nextBook = Queue.Current;
|
|
||||||
|
|
||||||
Serilog.Log.Logger.Information("Begin processing queued item. {item_LibraryBook}", nextBook?.LibraryBook);
|
|
||||||
|
|
||||||
var result = await nextBook.ProcessOneAsync();
|
|
||||||
|
|
||||||
Serilog.Log.Logger.Information("Completed processing queued item: {item_LibraryBook}\r\nResult: {result}", nextBook?.LibraryBook, result);
|
|
||||||
|
|
||||||
if (result == ProcessBookResult.ValidationFail)
|
|
||||||
Queue.ClearCurrent();
|
|
||||||
else if (result == ProcessBookResult.FailedAbort)
|
|
||||||
Queue.ClearQueue();
|
|
||||||
else if (result == ProcessBookResult.FailedSkip)
|
|
||||||
nextBook.LibraryBook.Book.UpdateBookStatus(DataLayer.LiberatedStatus.Error);
|
|
||||||
}
|
|
||||||
Serilog.Log.Logger.Information("Completed processing queue");
|
|
||||||
|
|
||||||
Queue_CompletedCountChanged(this, 0);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Serilog.Log.Logger.Error(ex, "An error was encountered while processing queued items");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#region Control event handlers
|
|
||||||
|
|
||||||
private void Queue_CompletedCountChanged(object sender, int e)
|
|
||||||
{
|
|
||||||
int errCount = Queue.Completed.Count(p => p.Result is ProcessBookResult.FailedAbort or ProcessBookResult.FailedSkip or ProcessBookResult.FailedRetry or ProcessBookResult.ValidationFail);
|
|
||||||
int completeCount = Queue.Completed.Count(p => p.Result is ProcessBookResult.Success);
|
|
||||||
|
|
||||||
ErrorCount = errCount;
|
|
||||||
CompletedCount = completeCount;
|
|
||||||
UpdateProgressBar();
|
|
||||||
}
|
|
||||||
private void Queue_QueuededCountChanged(object sender, int cueCount)
|
|
||||||
{
|
|
||||||
QueuedCount = cueCount;
|
|
||||||
UpdateProgressBar();
|
|
||||||
}
|
|
||||||
private void UpdateProgressBar()
|
|
||||||
{
|
|
||||||
double percent = 100d * Queue.Completed.Count / Queue.Count;
|
|
||||||
toolStripProgressBar1.Value = percent;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void cancelAllBtn_Click(object sender, EventArgs e)
|
private async void cancelAllBtn_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Queue.ClearQueue();
|
Queue.ClearQueue();
|
||||||
@ -350,22 +232,8 @@ namespace LibationWinForms.AvaloniaUI.Views
|
|||||||
{
|
{
|
||||||
Queue.ClearCompleted();
|
Queue.ClearCompleted();
|
||||||
|
|
||||||
if (!Running)
|
if (!_viewModel.Running)
|
||||||
runningTimeLbl.Text = string.Empty;
|
_viewModel.RunningTime = string.Empty;
|
||||||
}
|
|
||||||
|
|
||||||
private void CounterTimer_Tick(object? state)
|
|
||||||
{
|
|
||||||
string timeToStr(TimeSpan time)
|
|
||||||
{
|
|
||||||
string minsSecs = $"{time:mm\\:ss}";
|
|
||||||
if (time.TotalHours >= 1)
|
|
||||||
return $"{time.TotalHours:F0}:{minsSecs}";
|
|
||||||
return minsSecs;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Running)
|
|
||||||
Dispatcher.UIThread.Post(() => runningTimeLbl.Text = timeToStr(DateTime.Now - StartingTime));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@ -46,6 +46,7 @@ namespace LibationWinForms.AvaloniaUI.Views.ProductsGrid
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
//List is already displayed. Replace all items with new ones, refilter, and re-sort
|
||||||
string existingFilter = _viewModel?.GridEntries?.Filter;
|
string existingFilter = _viewModel?.GridEntries?.Filter;
|
||||||
bindingList.ReplaceList(ProductsDisplayViewModel.CreateGridEntries(dbBooks));
|
bindingList.ReplaceList(ProductsDisplayViewModel.CreateGridEntries(dbBooks));
|
||||||
bindingList.Filter = existingFilter;
|
bindingList.Filter = existingFilter;
|
||||||
|
|||||||
@ -46,6 +46,7 @@
|
|||||||
<None Remove="AvaloniaUI\Assets\edit_25x25.png" />
|
<None Remove="AvaloniaUI\Assets\edit_25x25.png" />
|
||||||
<None Remove="AvaloniaUI\Assets\errored.png" />
|
<None Remove="AvaloniaUI\Assets\errored.png" />
|
||||||
<None Remove="AvaloniaUI\Assets\first.png" />
|
<None Remove="AvaloniaUI\Assets\first.png" />
|
||||||
|
<None Remove="AvaloniaUI\Assets\glass-with-glow_16.png" />
|
||||||
<None Remove="AvaloniaUI\Assets\import_16x16.png" />
|
<None Remove="AvaloniaUI\Assets\import_16x16.png" />
|
||||||
<None Remove="AvaloniaUI\Assets\last.png" />
|
<None Remove="AvaloniaUI\Assets\last.png" />
|
||||||
<None Remove="AvaloniaUI\Assets\LibationStyles.xaml" />
|
<None Remove="AvaloniaUI\Assets\LibationStyles.xaml" />
|
||||||
|
|||||||
@ -5,7 +5,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
|||||||
<Project>
|
<Project>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration>Release</Configuration>
|
<Configuration>Release</Configuration>
|
||||||
<Platform>x64</Platform>
|
<Platform>Any CPU</Platform>
|
||||||
<PublishDir>..\bin\publish\</PublishDir>
|
<PublishDir>..\bin\publish\</PublishDir>
|
||||||
<PublishProtocol>FileSystem</PublishProtocol>
|
<PublishProtocol>FileSystem</PublishProtocol>
|
||||||
<TargetFramework>net6.0-windows</TargetFramework>
|
<TargetFramework>net6.0-windows</TargetFramework>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user