mirror of
https://github.com/rmcrackan/Libation.git
synced 2026-01-08 22:09:01 -05:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
042f2e135a | ||
|
|
930fc3da58 | ||
|
|
90e8d03590 | ||
|
|
ee908a4f13 | ||
|
|
70ec31303b | ||
|
|
319d547aa0 | ||
|
|
a59e42e7c9 | ||
|
|
af2e89dd1e | ||
|
|
b2c5884e11 | ||
|
|
11d9cdefe2 | ||
|
|
54485ae150 | ||
|
|
4bd641ee50 | ||
|
|
6e56297434 | ||
|
|
e1f59eadbd | ||
|
|
cfda065219 |
@@ -1 +1,3 @@
|
||||
# This page has been moved to https://getlibation.com/docs/advanced/advanced
|
||||
# This page has been moved to https://getlibation.com/docs/advanced/advanced
|
||||
|
||||
([page in github](https://github.com/rmcrackan/Libation/blob/master/docs/advanced/advanced.md))
|
||||
@@ -1 +1,3 @@
|
||||
# This page has been moved to https://getlibation.com/docs/features/audio-file-formats
|
||||
# This page has been moved to https://getlibation.com/docs/features/audio-file-formats
|
||||
|
||||
([page in github](https://github.com/rmcrackan/Libation/blob/master/docs/features/audio-file-formats.md))
|
||||
@@ -1 +1,3 @@
|
||||
# This page has been moved to https://getlibation.com/docs/installation/docker
|
||||
# This page has been moved to https://getlibation.com/docs/installation/docker
|
||||
|
||||
([page in github](https://github.com/rmcrackan/Libation/blob/master/docs/installation/docker.md))
|
||||
@@ -1 +1,3 @@
|
||||
# This page has been moved to https://getlibation.com/docs/frequently-asked-questions
|
||||
# This page has been moved to https://getlibation.com/docs/frequently-asked-questions
|
||||
|
||||
([page in github](https://github.com/rmcrackan/Libation/blob/master/docs/frequently-asked-questions.md))
|
||||
@@ -1 +1,3 @@
|
||||
# This page has been moved to https://getlibation.com/docs/getting-started
|
||||
# This page has been moved to https://getlibation.com/docs/getting-started
|
||||
|
||||
([page in github](https://github.com/rmcrackan/Libation/blob/master/docs/getting-started.md))
|
||||
@@ -1 +1,3 @@
|
||||
# This page has been moved to https://getlibation.com/docs/installation/linux
|
||||
# This page has been moved to https://getlibation.com/docs/installation/linux
|
||||
|
||||
([page in github](https://github.com/rmcrackan/Libation/blob/master/docs/installation/linux.md))
|
||||
@@ -1 +1,3 @@
|
||||
# This page has been moved to https://getlibation.com/docs/installation/mac
|
||||
# This page has been moved to https://getlibation.com/docs/installation/mac
|
||||
|
||||
([page in github](https://github.com/rmcrackan/Libation/blob/master/docs/installation/mac.md))
|
||||
@@ -1 +1,3 @@
|
||||
# This page has been moved to https://getlibation.com/docs/development/nix-linux-setup
|
||||
# This page has been moved to https://getlibation.com/docs/development/nix-linux-setup
|
||||
|
||||
([page in github](https://github.com/rmcrackan/Libation/blob/master/docs/development/nix-linux-setup.md))
|
||||
@@ -1 +1,3 @@
|
||||
# This page has been moved to https://getlibation.com/docs/features/naming-templates
|
||||
# This page has been moved to https://getlibation.com/docs/features/naming-templates
|
||||
|
||||
([page in github](https://github.com/rmcrackan/Libation/blob/master/docs/features/naming-templates.md))
|
||||
@@ -1 +1,3 @@
|
||||
# This page has been moved to https://getlibation.com/docs/features/searching-and-filtering
|
||||
# This page has been moved to https://getlibation.com/docs/features/searching-and-filtering
|
||||
|
||||
([page in github](https://github.com/rmcrackan/Libation/blob/master/docs/features/searching-and-filtering.md))
|
||||
@@ -2,7 +2,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Version>13.1.0.1</Version>
|
||||
<Version>13.1.1.1</Version>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Octokit" Version="14.0.0" />
|
||||
|
||||
@@ -322,7 +322,7 @@ namespace FileLiberator
|
||||
catch (Exception ex)
|
||||
{
|
||||
//Failure to determine output audio format should not be considered a failure to download the book
|
||||
Serilog.Log.Logger.Error(ex, "Error determining output audio format for {@Book}. File = '{@audioFile}'", options.LibraryBook, firstAudioFile);
|
||||
Serilog.Log.Logger.Error(ex, "Error determining output audio format for {@Book}. File = '{@audioFile}'", options.LibraryBook.LogFriendly(), firstAudioFile);
|
||||
return AudioFormat.Default;
|
||||
}
|
||||
|
||||
@@ -427,7 +427,7 @@ namespace FileLiberator
|
||||
{
|
||||
//Failure to download cover art should not be considered a failure to download the book
|
||||
if (!cancellationToken.IsCancellationRequested)
|
||||
Serilog.Log.Logger.Error(ex, "Error downloading cover art for {@Book} to {@metadataFile}.", options.LibraryBook, coverPath);
|
||||
Serilog.Log.Logger.Error(ex, "Error downloading cover art for {@Book} to {@metadataFile}.", options.LibraryBook.LogFriendly(), coverPath);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
@@ -476,7 +476,7 @@ namespace FileLiberator
|
||||
{
|
||||
//Failure to download records should not be considered a failure to download the book
|
||||
if (!cancellationToken.IsCancellationRequested)
|
||||
Serilog.Log.Logger.Error(ex, "Error downloading clips and bookmarks for {@Book} to {@recordsPath}.", options.LibraryBook, recordsPath);
|
||||
Serilog.Log.Logger.Error(ex, "Error downloading clips and bookmarks for {@Book} to {@recordsPath}.", options.LibraryBook.LogFriendly(), recordsPath);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
@@ -512,7 +512,7 @@ namespace FileLiberator
|
||||
{
|
||||
//Failure to download metadata should not be considered a failure to download the book
|
||||
if (!cancellationToken.IsCancellationRequested)
|
||||
Serilog.Log.Logger.Error(ex, "Error downloading metdatat of {@Book} to {@metadataFile}.", options.LibraryBook, metadataPath);
|
||||
Serilog.Log.Logger.Error(ex, "Error downloading metadata of {@Book} to {@metadataFile}.", options.LibraryBook.LogFriendly(), metadataPath);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d" d:DesignWidth="600" d:DesignHeight="450"
|
||||
xmlns:uibase="clr-namespace:LibationUiBase;assembly=LibationUiBase"
|
||||
x:DataType="uibase:LocatedAudiobooksViewModel"
|
||||
x:CompileBindings="True"
|
||||
Width="600" Height="450"
|
||||
x:Class="LibationAvalonia.Dialogs.LocateAudiobooksDialog"
|
||||
Title="Locate Audiobooks"
|
||||
@@ -13,17 +16,34 @@
|
||||
<StackPanel Grid.Column="1" Orientation="Horizontal">
|
||||
|
||||
<TextBlock Text="IDs Found: " />
|
||||
<TextBlock Text="{Binding FoundAsins}" />
|
||||
<TextBlock Text="{Binding FoundAsinCount}" />
|
||||
</StackPanel>
|
||||
<ListBox Margin="0,5,0,0" Grid.Row="1" Grid.ColumnSpan="2" Name="foundAudiobooksLB" ItemsSource="{Binding FoundFiles}" AutoScrollToSelectedItem="true">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid ColumnDefinitions="Auto,*">
|
||||
<TextBlock Grid.Column="0" Margin="0,0,10,0" Text="{Binding Item1}" />
|
||||
<TextBlock Grid.Column="1" Text="{Binding Item2}" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
<DataGrid
|
||||
Margin="0,5,0,0"
|
||||
Grid.Row="1"
|
||||
Grid.ColumnSpan="2"
|
||||
IsReadOnly="True"
|
||||
CanUserSortColumns="True"
|
||||
CanUserResizeColumns="True"
|
||||
GridLinesVisibility="All"
|
||||
DoubleTapped="foundFilesDataGrid_DoubleTapped"
|
||||
Name="foundFilesDataGrid"
|
||||
ItemsSource="{Binding FoundFiles}">
|
||||
<DataGrid.Styles>
|
||||
<Style Selector="DataGridCell TextBlock">
|
||||
<Setter Property="ToolTip.Tip" Value="Double-click to open containing folder."/>
|
||||
</Style>
|
||||
</DataGrid.Styles>
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn
|
||||
Header="Found ID"
|
||||
Width="Auto"
|
||||
Binding="{Binding ID}" />
|
||||
<DataGridTextColumn
|
||||
Header="Found File"
|
||||
Width="*"
|
||||
Binding="{Binding FileName}" />
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</Grid>
|
||||
</Window>
|
||||
|
||||
@@ -1,41 +1,39 @@
|
||||
using ApplicationServices;
|
||||
using Avalonia.Collections;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Platform.Storage;
|
||||
using DataLayer;
|
||||
using LibationAvalonia.ViewModels;
|
||||
using Dinah.Core;
|
||||
using LibationFileManager;
|
||||
using ReactiveUI;
|
||||
using LibationUiBase;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading;
|
||||
|
||||
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();
|
||||
var list = new AvaloniaList<FoundAudiobook>();
|
||||
DataContext = _viewModel = new(list);
|
||||
list.CollectionChanged += (_, _) => foundFilesDataGrid.ScrollIntoView(list[^1], foundFilesDataGrid.Columns[0]);
|
||||
this.RestoreSizeAndLocation(Configuration.Instance);
|
||||
|
||||
if (Design.IsDesignMode)
|
||||
{
|
||||
_viewModel.FoundFiles.Add(new("[0000001]", "Filename 1.m4b"));
|
||||
_viewModel.FoundFiles.Add(new("[0000002]", "Filename 2.m4b"));
|
||||
_viewModel.AddFoundFile(new("0000000001", FileType.Audio, "Filename 1.m4b"));
|
||||
_viewModel.AddFoundFile(new("0000000002", FileType.Audio, "Filename 2.m4b"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Opened += LocateAudiobooksDialog_Opened;
|
||||
FileFound += LocateAudiobooks_FileFound;
|
||||
Closing += LocateAudiobooksDialog_Closing;
|
||||
}
|
||||
}
|
||||
@@ -49,19 +47,6 @@ namespace LibationAvalonia.Dialogs
|
||||
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
|
||||
@@ -76,37 +61,18 @@ namespace LibationAvalonia.Dialogs
|
||||
if (selectedFolder is null || !Directory.Exists(selectedFolder))
|
||||
{
|
||||
await CancelAndCloseAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
await foreach (var book in AudioFileStorage.FindAudiobooksAsync(selectedFolder, tokenSource.Token))
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
FilePathCache.Insert(book);
|
||||
|
||||
var lb = DbContexts.GetLibraryBook_Flat_NoTracking(book.Id);
|
||||
if (lb is not null && lb.Book?.UserDefinedItem.BookStatus is not LiberatedStatus.Liberated)
|
||||
await lb.UpdateBookStatusAsync(LiberatedStatus.Liberated);
|
||||
|
||||
tokenSource.Token.ThrowIfCancellationRequested();
|
||||
FileFound?.Invoke(this, book);
|
||||
}
|
||||
catch (OperationCanceledException) { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
Serilog.Log.Error(ex, "Error adding found audiobook file to Libation. {@audioFile}", book);
|
||||
}
|
||||
await _viewModel.FindAndAddBooksAsync(selectedFolder, tokenSource.Token);
|
||||
await MessageBox.Show(this, $"Libation has found {_viewModel.FoundAsinCount} unique audiobooks and added them to its database. ", $"Found {_viewModel.FoundAsinCount} Audiobooks");
|
||||
}
|
||||
}
|
||||
|
||||
await MessageBox.Show(this, $"Libation has found {foundAsins.Count} unique audiobooks and added them to its database. ", $"Found {foundAsins.Count} Audiobooks");
|
||||
await SaveAndCloseAsync();
|
||||
private void foundFilesDataGrid_DoubleTapped(object? sender, Avalonia.Input.TappedEventArgs e)
|
||||
{
|
||||
if (sender is DataGrid dg && dg.SelectedItem is FoundAudiobook foundAudiobook)
|
||||
Go.To.File(foundAudiobook.Entry.Path);
|
||||
}
|
||||
}
|
||||
|
||||
public class LocatedAudiobooksViewModel : ViewModelBase
|
||||
{
|
||||
public AvaloniaList<Tuple<string, string>> FoundFiles { get; } = new();
|
||||
public int FoundAsins { get => field; set => this.RaiseAndSetIfChanged(ref field, value); }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ public class LibationContributor
|
||||
GitHubUser("twsouthwick"),
|
||||
GitHubUser("radiorambo"),
|
||||
GitHubUser("Youssef1313"),
|
||||
GitHubUser("niontrix"),
|
||||
]);
|
||||
|
||||
private LibationContributor(string name, LibationContributorType type,Uri link)
|
||||
|
||||
71
Source/LibationUiBase/LocatedAudiobooksViewModel.cs
Normal file
71
Source/LibationUiBase/LocatedAudiobooksViewModel.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
using ApplicationServices;
|
||||
using DataLayer;
|
||||
using LibationFileManager;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LibationUiBase;
|
||||
|
||||
public class FoundAudiobook
|
||||
{
|
||||
public string ID => Entry.Id;
|
||||
public string FileName { get; }
|
||||
public FilePathCache.CacheEntry Entry { get; }
|
||||
public FoundAudiobook(FilePathCache.CacheEntry entry)
|
||||
{
|
||||
Entry = entry;
|
||||
FileName = Path.GetFileName(entry.Path);
|
||||
}
|
||||
}
|
||||
public class LocatedAudiobooksViewModel : ReactiveObject
|
||||
{
|
||||
public IList<FoundAudiobook> FoundFiles { get; }
|
||||
public int FoundAsinCount { get => field; private set => RaiseAndSetIfChanged(ref field, value); }
|
||||
private readonly HashSet<string> foundAsinsSet = [];
|
||||
public LocatedAudiobooksViewModel(IList<FoundAudiobook> fileList)
|
||||
{
|
||||
FoundFiles = fileList;
|
||||
}
|
||||
|
||||
public void AddFoundFile(FilePathCache.CacheEntry entry)
|
||||
{
|
||||
FoundAudiobook foundFile = new(entry);
|
||||
Invoke(() => FoundFiles?.Add(foundFile));
|
||||
if (!foundAsinsSet.Contains(entry.Id))
|
||||
{
|
||||
foundAsinsSet.Add(entry.Id);
|
||||
FoundAsinCount = foundAsinsSet.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task FindAndAddBooksAsync(string searchdir, CancellationToken cancellation)
|
||||
{
|
||||
await Task.Run(() => FindAndAddBooksInternal(searchdir, cancellation), cancellation).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task FindAndAddBooksInternal(string searchdir, CancellationToken cancellation)
|
||||
{
|
||||
await foreach (var book in AudioFileStorage.FindAudiobooksAsync(searchdir, cancellation))
|
||||
{
|
||||
try
|
||||
{
|
||||
FilePathCache.Insert(book);
|
||||
|
||||
var lb = DbContexts.GetLibraryBook_Flat_NoTracking(book.Id);
|
||||
if (lb is not null && lb.Book?.UserDefinedItem.BookStatus is not LiberatedStatus.Liberated)
|
||||
await lb.UpdateBookStatusAsync(LiberatedStatus.Liberated);
|
||||
|
||||
cancellation.ThrowIfCancellationRequested();
|
||||
AddFoundFile(book);
|
||||
}
|
||||
catch (OperationCanceledException) { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
Serilog.Log.Error(ex, "Error adding found audiobook file to Libation. {@audioFile}", book);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,80 +28,111 @@
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.foundAudiobooksLV = new System.Windows.Forms.ListView();
|
||||
this.columnHeader1 = new System.Windows.Forms.ColumnHeader();
|
||||
this.columnHeader2 = new System.Windows.Forms.ColumnHeader();
|
||||
this.booksFoundLbl = new System.Windows.Forms.Label();
|
||||
this.SuspendLayout();
|
||||
components = new System.ComponentModel.Container();
|
||||
label1 = new System.Windows.Forms.Label();
|
||||
booksFoundLbl = new System.Windows.Forms.Label();
|
||||
dataGridView1 = new System.Windows.Forms.DataGridView();
|
||||
foundAudiobookBindingSource = new System.Windows.Forms.BindingSource(components);
|
||||
iDDataGridViewTextBoxColumn = new AccessibleDataGridViewColumn();
|
||||
fileNameDataGridViewTextBoxColumn = new AccessibleDataGridViewColumn();
|
||||
((System.ComponentModel.ISupportInitialize)dataGridView1).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)foundAudiobookBindingSource).BeginInit();
|
||||
SuspendLayout();
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Location = new System.Drawing.Point(12, 9);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(108, 15);
|
||||
this.label1.TabIndex = 1;
|
||||
this.label1.Text = "Found Audiobooks";
|
||||
//
|
||||
// foundAudiobooksLV
|
||||
//
|
||||
this.foundAudiobooksLV.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.foundAudiobooksLV.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
|
||||
this.columnHeader1,
|
||||
this.columnHeader2});
|
||||
this.foundAudiobooksLV.FullRowSelect = true;
|
||||
this.foundAudiobooksLV.Location = new System.Drawing.Point(12, 33);
|
||||
this.foundAudiobooksLV.Name = "foundAudiobooksLV";
|
||||
this.foundAudiobooksLV.Size = new System.Drawing.Size(321, 261);
|
||||
this.foundAudiobooksLV.TabIndex = 2;
|
||||
this.foundAudiobooksLV.UseCompatibleStateImageBehavior = false;
|
||||
this.foundAudiobooksLV.View = System.Windows.Forms.View.Details;
|
||||
//
|
||||
// columnHeader1
|
||||
//
|
||||
this.columnHeader1.Text = "Book ID";
|
||||
this.columnHeader1.Width = 85;
|
||||
//
|
||||
// columnHeader2
|
||||
//
|
||||
this.columnHeader2.Text = "Title";
|
||||
label1.AutoSize = true;
|
||||
label1.Location = new System.Drawing.Point(12, 9);
|
||||
label1.Name = "label1";
|
||||
label1.Size = new System.Drawing.Size(108, 15);
|
||||
label1.TabIndex = 1;
|
||||
label1.Text = "Found Audiobooks";
|
||||
//
|
||||
// booksFoundLbl
|
||||
//
|
||||
this.booksFoundLbl.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.booksFoundLbl.AutoSize = true;
|
||||
this.booksFoundLbl.Location = new System.Drawing.Point(253, 9);
|
||||
this.booksFoundLbl.Name = "booksFoundLbl";
|
||||
this.booksFoundLbl.Size = new System.Drawing.Size(80, 15);
|
||||
this.booksFoundLbl.TabIndex = 3;
|
||||
this.booksFoundLbl.Text = "IDs Found: {0}";
|
||||
this.booksFoundLbl.TextAlign = System.Drawing.ContentAlignment.TopRight;
|
||||
booksFoundLbl.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
|
||||
booksFoundLbl.AutoSize = true;
|
||||
booksFoundLbl.Location = new System.Drawing.Point(253, 9);
|
||||
booksFoundLbl.Name = "booksFoundLbl";
|
||||
booksFoundLbl.Size = new System.Drawing.Size(72, 15);
|
||||
booksFoundLbl.TabIndex = 3;
|
||||
booksFoundLbl.Text = "IDs Found: 0";
|
||||
booksFoundLbl.TextAlign = System.Drawing.ContentAlignment.TopRight;
|
||||
//
|
||||
// dataGridView1
|
||||
//
|
||||
dataGridView1.AllowUserToAddRows = false;
|
||||
dataGridView1.AllowUserToDeleteRows = false;
|
||||
dataGridView1.AllowUserToResizeRows = false;
|
||||
dataGridView1.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
|
||||
dataGridView1.AutoGenerateColumns = false;
|
||||
dataGridView1.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.AllCells;
|
||||
dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
|
||||
dataGridView1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { iDDataGridViewTextBoxColumn, fileNameDataGridViewTextBoxColumn });
|
||||
dataGridView1.DataSource = foundAudiobookBindingSource;
|
||||
dataGridView1.Location = new System.Drawing.Point(12, 27);
|
||||
dataGridView1.Name = "dataGridView1";
|
||||
dataGridView1.RowHeadersVisible = false;
|
||||
dataGridView1.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.CellSelect;
|
||||
dataGridView1.Size = new System.Drawing.Size(321, 267);
|
||||
dataGridView1.TabIndex = 4;
|
||||
dataGridView1.CellDoubleClick += dataGridView1_CellDoubleClick;
|
||||
//
|
||||
// foundAudiobookBindingSource
|
||||
//
|
||||
foundAudiobookBindingSource.DataSource = typeof(LibationUiBase.FoundAudiobook);
|
||||
//
|
||||
// iDDataGridViewTextBoxColumn
|
||||
//
|
||||
iDDataGridViewTextBoxColumn.AccessibilityDescription = "Audiobook's Audible product ID forund by the scan.";
|
||||
iDDataGridViewTextBoxColumn.AccessibilityName = "Found ASIN";
|
||||
iDDataGridViewTextBoxColumn.DataPropertyName = "ID";
|
||||
iDDataGridViewTextBoxColumn.HeaderText = "Found ID";
|
||||
iDDataGridViewTextBoxColumn.Name = "iDDataGridViewTextBoxColumn";
|
||||
iDDataGridViewTextBoxColumn.ReadOnly = true;
|
||||
iDDataGridViewTextBoxColumn.Resizable = System.Windows.Forms.DataGridViewTriState.True;
|
||||
iDDataGridViewTextBoxColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Automatic;
|
||||
iDDataGridViewTextBoxColumn.Width = 80;
|
||||
//
|
||||
// fileNameDataGridViewTextBoxColumn
|
||||
//
|
||||
fileNameDataGridViewTextBoxColumn.AccessibilityDescription = "Audiobook file found. Double-click to open containing folder.";
|
||||
fileNameDataGridViewTextBoxColumn.AccessibilityName = "Found File";
|
||||
fileNameDataGridViewTextBoxColumn.DataPropertyName = "FileName";
|
||||
fileNameDataGridViewTextBoxColumn.HeaderText = "Found File";
|
||||
fileNameDataGridViewTextBoxColumn.Name = "fileNameDataGridViewTextBoxColumn";
|
||||
fileNameDataGridViewTextBoxColumn.ReadOnly = true;
|
||||
fileNameDataGridViewTextBoxColumn.Resizable = System.Windows.Forms.DataGridViewTriState.True;
|
||||
fileNameDataGridViewTextBoxColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Automatic;
|
||||
fileNameDataGridViewTextBoxColumn.Width = 87;
|
||||
//
|
||||
// LocateAudiobooksDialog
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
|
||||
this.ClientSize = new System.Drawing.Size(345, 306);
|
||||
this.Controls.Add(this.booksFoundLbl);
|
||||
this.Controls.Add(this.foundAudiobooksLV);
|
||||
this.Controls.Add(this.label1);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;
|
||||
this.Name = "LocateAudiobooksDialog";
|
||||
this.Text = "Locate Audiobooks";
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
|
||||
AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
|
||||
ClientSize = new System.Drawing.Size(345, 306);
|
||||
Controls.Add(dataGridView1);
|
||||
Controls.Add(booksFoundLbl);
|
||||
Controls.Add(label1);
|
||||
FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;
|
||||
Name = "LocateAudiobooksDialog";
|
||||
Text = "Locate Audiobooks";
|
||||
FormClosing += LocateAudiobooks_FormClosing;
|
||||
Shown += LocateAudiobooks_Shown;
|
||||
((System.ComponentModel.ISupportInitialize)dataGridView1).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)foundAudiobookBindingSource).EndInit();
|
||||
ResumeLayout(false);
|
||||
PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.ListView foundAudiobooksLV;
|
||||
private System.Windows.Forms.ColumnHeader columnHeader1;
|
||||
private System.Windows.Forms.ColumnHeader columnHeader2;
|
||||
private System.Windows.Forms.Label booksFoundLbl;
|
||||
private System.Windows.Forms.DataGridView dataGridView1;
|
||||
private System.Windows.Forms.BindingSource foundAudiobookBindingSource;
|
||||
private AccessibleDataGridViewColumn iDDataGridViewTextBoxColumn;
|
||||
private AccessibleDataGridViewColumn fileNameDataGridViewTextBoxColumn;
|
||||
}
|
||||
}
|
||||
@@ -1,53 +1,35 @@
|
||||
using ApplicationServices;
|
||||
using DataLayer;
|
||||
using DataLayer;
|
||||
using Dinah.Core;
|
||||
using LibationFileManager;
|
||||
using LibationUiBase;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace LibationWinForms.Dialogs
|
||||
{
|
||||
public partial class LocateAudiobooksDialog : Form
|
||||
{
|
||||
private event EventHandler<FilePathCache.CacheEntry> FileFound;
|
||||
private readonly CancellationTokenSource tokenSource = new();
|
||||
private readonly List<string> foundAsins = new();
|
||||
private readonly string labelFormatText;
|
||||
private readonly LocatedAudiobooksViewModel _viewModel;
|
||||
public LocateAudiobooksDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
labelFormatText = booksFoundLbl.Text;
|
||||
setFoundBookCount(0);
|
||||
|
||||
this.SetLibationIcon();
|
||||
this.RestoreSizeAndLocation(Configuration.Instance);
|
||||
|
||||
Shown += LocateAudiobooks_Shown;
|
||||
FileFound += LocateAudiobooks_FileFound;
|
||||
FormClosing += LocateAudiobooks_FormClosing;
|
||||
_viewModel = new LocatedAudiobooksViewModel(new SortBindingList<FoundAudiobook>());
|
||||
dataGridView1.EnableHeadersVisualStyles = !Application.IsDarkModeEnabled;
|
||||
dataGridView1.RowsAdded += DataGridView1_RowsAdded;
|
||||
foundAudiobookBindingSource.DataSource = _viewModel.FoundFiles;
|
||||
booksFoundLbl.DataBindings.Add(new Binding(nameof(booksFoundLbl.Text), _viewModel, nameof(_viewModel.FoundAsinCount), true, DataSourceUpdateMode.OnPropertyChanged, 0, booksFoundLbl.Text));
|
||||
}
|
||||
|
||||
private void setFoundBookCount(int count)
|
||||
=> booksFoundLbl.Text = string.Format(labelFormatText, count);
|
||||
|
||||
private void LocateAudiobooks_FileFound(object sender, FilePathCache.CacheEntry e)
|
||||
private void DataGridView1_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
|
||||
{
|
||||
foundAudiobooksLV.Items
|
||||
.Add(new ListViewItem(new string[] { $"[{e.Id}]", Path.GetFileName(e.Path) }))
|
||||
.EnsureVisible();
|
||||
|
||||
foundAudiobooksLV.AutoResizeColumn(1, ColumnHeaderAutoResizeStyle.ColumnContent);
|
||||
|
||||
if (!foundAsins.Any(asin => asin == e.Id))
|
||||
{
|
||||
foundAsins.Add(e.Id);
|
||||
setFoundBookCount(foundAsins.Count);
|
||||
}
|
||||
dataGridView1.FirstDisplayedScrollingRowIndex = e.RowIndex;
|
||||
}
|
||||
|
||||
private void LocateAudiobooks_FormClosing(object sender, FormClosingEventArgs e)
|
||||
@@ -65,34 +47,22 @@ namespace LibationWinForms.Dialogs
|
||||
InitialDirectory = Configuration.Instance.Books
|
||||
};
|
||||
|
||||
if (fbd.ShowDialog() != DialogResult.OK || !Directory.Exists(fbd.SelectedPath))
|
||||
var result = fbd.ShowDialog(this);
|
||||
if (result != DialogResult.OK || !Directory.Exists(fbd.SelectedPath))
|
||||
{
|
||||
Close();
|
||||
return;
|
||||
DialogResult = result;
|
||||
}
|
||||
|
||||
await foreach (var book in AudioFileStorage.FindAudiobooksAsync(fbd.SelectedPath, tokenSource.Token))
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
FilePathCache.Insert(book);
|
||||
|
||||
var lb = DbContexts.GetLibraryBook_Flat_NoTracking(book.Id);
|
||||
if (lb.Book.UserDefinedItem.BookStatus is not LiberatedStatus.Liberated)
|
||||
await lb.UpdateBookStatusAsync(LiberatedStatus.Liberated);
|
||||
|
||||
tokenSource.Token.ThrowIfCancellationRequested();
|
||||
this.Invoke(FileFound, this, book);
|
||||
}
|
||||
catch (OperationCanceledException) { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
Serilog.Log.Error(ex, "Error adding found audiobook file to Libation. {@audioFile}", book);
|
||||
}
|
||||
await _viewModel.FindAndAddBooksAsync(fbd.SelectedPath, tokenSource.Token);
|
||||
MessageBox.Show(this, $"Libation has found {_viewModel.FoundAsinCount} unique audiobooks and added them to its database. ", $"Found {_viewModel.FoundAsinCount} Audiobooks");
|
||||
}
|
||||
}
|
||||
|
||||
MessageBox.Show(this, $"Libation has found {foundAsins.Count} unique audiobooks and added them to its database. ", $"Found {foundAsins.Count} Audiobooks");
|
||||
Close();
|
||||
private void dataGridView1_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
|
||||
{
|
||||
if (e.RowIndex >= 0 && e.RowIndex < _viewModel.FoundFiles.Count)
|
||||
Go.To.File(_viewModel.FoundFiles[e.RowIndex].Entry.Path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,21 +24,6 @@ namespace LibationWinForms.Dialogs
|
||||
releaseNotesTbox.Text = upgradeProperties.Notes;
|
||||
|
||||
Shown += (_, _) => yesBtn.Focus();
|
||||
Load += UpgradeNotificationDialog_Load;
|
||||
}
|
||||
|
||||
private void UpgradeNotificationDialog_Load(object sender, EventArgs e)
|
||||
{
|
||||
//This dialog starts before Form1, soposition it at the center of where Form1 will be.
|
||||
var savedState = Configuration.Instance.GetNonString<FormSizeAndPosition>(defaultValue: null, nameof(Form1));
|
||||
|
||||
if (savedState is null) return;
|
||||
|
||||
int x = savedState.X + (savedState.Width - Width) / 2;
|
||||
int y = savedState.Y + (savedState.Height - Height) / 2;
|
||||
|
||||
Location = new(x, y);
|
||||
TopMost = true;
|
||||
}
|
||||
|
||||
private void PackageDlLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||
|
||||
@@ -11,14 +11,12 @@ namespace LibationWinForms
|
||||
{
|
||||
setProgressVisible(false);
|
||||
#pragma warning disable CS8321 // Local function is declared but never used
|
||||
Task upgradeAvailable(UpgradeEventArgs e)
|
||||
async Task upgradeAvailable(UpgradeEventArgs e)
|
||||
{
|
||||
var notificationResult = new UpgradeNotificationDialog(e.UpgradeProperties).ShowDialog(this);
|
||||
var notificationResult = await new UpgradeNotificationDialog(e.UpgradeProperties).ShowDialogAsync(this);
|
||||
|
||||
e.Ignore = notificationResult == DialogResult.Ignore;
|
||||
e.InstallUpgrade = notificationResult == DialogResult.Yes;
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
#pragma warning restore CS8321 // Local function is declared but never used
|
||||
|
||||
|
||||
@@ -69,6 +69,16 @@ Thanks to [mhdi](https://aur.archlinux.org/account/mhdi) for taking care of AUR
|
||||
|
||||
Thanks to [TomaSajt](https://github.com/tomasajt) for taking care of Nix package maintenance.
|
||||
|
||||
### Pacstall
|
||||
|
||||
Pacstall is the AUR Ubuntu wishes it had. It takes the concept of the AUR and puts a spin on it, making it easier to install programs without scouring github repos and the likes. See the [Pacstall](https://pacstall.dev/) project for more information.
|
||||
|
||||
```bash
|
||||
pacstall -I libation-deb
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
If your desktop uses gtk, you should now see Libation among your applications.
|
||||
|
||||
Additionally, you may launch Libation, LibationCli, and Hangover (the Libation recovery app) via the command line using 'libation, libationcli', and 'hangover' aliases respectively.
|
||||
|
||||
Reference in New Issue
Block a user