Libation/Source/LibationAvalonia/Dialogs/LocateAudiobooksDialog.axaml.cs

116 lines
3.6 KiB
C#

using ApplicationServices;
using Avalonia.Collections;
using Avalonia.Controls;
using Avalonia.Platform.Storage;
using Avalonia.Platform.Storage.FileIO;
using DataLayer;
using LibationAvalonia.ViewModels;
using LibationFileManager;
using ReactiveUI;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace LibationAvalonia.Dialogs
{
public partial class LocateAudiobooksDialog : DialogWindow
{
private event EventHandler<FilePathCache.CacheEntry> FileFound;
private readonly CancellationTokenSource tokenSource = new();
private readonly List<string> foundAsins = new();
private readonly LocatedAudiobooksViewModel _viewModel;
public LocateAudiobooksDialog()
{
InitializeComponent();
DataContext = _viewModel = new();
this.RestoreSizeAndLocation(Configuration.Instance);
if (Design.IsDesignMode)
{
_viewModel.FoundFiles.Add(new("[0000001]", "Filename 1.m4b"));
_viewModel.FoundFiles.Add(new("[0000002]", "Filename 2.m4b"));
}
else
{
Opened += LocateAudiobooksDialog_Opened;
FileFound += LocateAudiobooks_FileFound;
Closing += LocateAudiobooksDialog_Closing;
}
}
private void LocateAudiobooksDialog_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
tokenSource.Cancel();
//If this dialog is closed before it's completed, Closing is fired
//once for the form closing and again for the MessageBox closing.
Closing -= LocateAudiobooksDialog_Closing;
this.SaveSizeAndLocation(Configuration.Instance);
}
private void LocateAudiobooks_FileFound(object sender, FilePathCache.CacheEntry e)
{
var newItem = new Tuple<string,string>($"[{e.Id}]", Path.GetFileName(e.Path));
_viewModel.FoundFiles.Add(newItem);
foundAudiobooksLB.SelectedItem = newItem;
if (!foundAsins.Any(asin => asin == e.Id))
{
foundAsins.Add(e.Id);
_viewModel.FoundAsins = foundAsins.Count;
}
}
private async void LocateAudiobooksDialog_Opened(object sender, EventArgs e)
{
var folderPicker = new FolderPickerOpenOptions
{
Title = "Select the folder to search for audiobooks",
AllowMultiple = false,
SuggestedStartLocation = new BclStorageFolder(Configuration.Instance.Books.PathWithoutPrefix)
};
var selectedFolder = await StorageProvider.OpenFolderPickerAsync(folderPicker);
if (selectedFolder.FirstOrDefault().TryGetUri(out var uri) is not true || !Directory.Exists(uri.LocalPath))
{
await CancelAndCloseAsync();
return;
}
using var context = DbContexts.GetContext();
await foreach (var book in AudioFileLocator.FindAudiobooks(uri.LocalPath, tokenSource.Token))
{
try
{
FilePathCache.Insert(book);
var lb = context.GetLibraryBook_Flat_NoTracking(book.Id);
if (lb.Book.UserDefinedItem.BookStatus is not LiberatedStatus.Liberated)
await Task.Run(() => lb.UpdateBookStatus(LiberatedStatus.Liberated));
FileFound?.Invoke(this, book);
}
catch (Exception ex)
{
Serilog.Log.Error(ex, "Error adding found audiobook file to Libation. {@audioFile}", book);
}
}
await MessageBox.Show(this, $"Libation has found {foundAsins.Count} unique audiobooks and added them to its database. ", $"Found {foundAsins.Count} Audiobooks");
await SaveAndCloseAsync();
}
}
public class LocatedAudiobooksViewModel : ViewModelBase
{
private int _foundAsins = 0;
public AvaloniaList<Tuple<string, string>> FoundFiles { get; } = new();
public int FoundAsins { get => _foundAsins; set => this.RaiseAndSetIfChanged(ref _foundAsins, value); }
}
}