Compare commits
27 Commits
v3.1-beta.
...
v3.1-beta.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de66e5b405 | ||
|
|
73c671b7c0 | ||
|
|
4994684690 | ||
|
|
6c757773f7 | ||
|
|
2d0af587d5 | ||
|
|
c7891dc448 | ||
|
|
95ae8335a1 | ||
|
|
2fa5170f28 | ||
|
|
123a32ff9b | ||
|
|
41620352e8 | ||
|
|
54eea8ddae | ||
|
|
bcc237c693 | ||
|
|
65dc273e12 | ||
|
|
7bb4853903 | ||
|
|
f9917d4064 | ||
|
|
0f9f0d9eae | ||
|
|
498aeaac3a | ||
|
|
9534969c2d | ||
|
|
b120bb8a66 | ||
|
|
f8a51f0882 | ||
|
|
7529fdf878 | ||
|
|
f1aacd92ad | ||
|
|
b1b426427c | ||
|
|
0683e5f55b | ||
|
|
5c81441f83 | ||
|
|
57bc74cd23 | ||
|
|
1cecd4ba2e |
@@ -72,8 +72,9 @@ namespace AaxDecrypter
|
||||
}
|
||||
private AaxToM4bConverter(string inputFile, string decryptKey)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(inputFile)) throw new ArgumentNullException(nameof(inputFile), "Input file may not be null or whitespace");
|
||||
if (!File.Exists(inputFile)) throw new ArgumentNullException(nameof(inputFile), "File does not exist");
|
||||
ArgumentValidator.EnsureNotNullOrWhiteSpace(inputFile, nameof(inputFile));
|
||||
if (!File.Exists(inputFile))
|
||||
throw new ArgumentNullException(nameof(inputFile), "File does not exist");
|
||||
|
||||
steps = new StepSequence
|
||||
{
|
||||
@@ -89,22 +90,24 @@ namespace AaxDecrypter
|
||||
["End: Create Nfo"] = End_CreateNfo
|
||||
};
|
||||
|
||||
this.inputFileName = inputFile;
|
||||
inputFileName = inputFile;
|
||||
this.decryptKey = decryptKey;
|
||||
}
|
||||
|
||||
private async Task prelimProcessing()
|
||||
{
|
||||
this.tags = new Tags(this.inputFileName);
|
||||
this.encodingInfo = new EncodingInfo(this.inputFileName);
|
||||
this.chapters = new Chapters(this.inputFileName, this.tags.duration.TotalSeconds);
|
||||
tags = new Tags(inputFileName);
|
||||
encodingInfo = new EncodingInfo(inputFileName);
|
||||
chapters = new Chapters(inputFileName, tags.duration.TotalSeconds);
|
||||
|
||||
var defaultFilename = Path.Combine(
|
||||
Path.GetDirectoryName(this.inputFileName),
|
||||
getASCIITag(this.tags.author),
|
||||
getASCIITag(this.tags.title) + ".m4b"
|
||||
Path.GetDirectoryName(inputFileName),
|
||||
getASCIITag(tags.author),
|
||||
getASCIITag(tags.title) + ".m4b"
|
||||
);
|
||||
SetOutputFilename(defaultFilename);
|
||||
|
||||
// set default name
|
||||
SetOutputFilename(defaultFilename);
|
||||
|
||||
await Task.Run(() => saveCover(inputFileName));
|
||||
}
|
||||
@@ -118,7 +121,7 @@ namespace AaxDecrypter
|
||||
private void saveCover(string aaxFile)
|
||||
{
|
||||
using var file = TagLib.File.Create(aaxFile, "audio/mp4", TagLib.ReadStyle.Average);
|
||||
this.coverBytes = file.Tag.Pictures[0].Data.Data;
|
||||
coverBytes = file.Tag.Pictures[0].Data.Data;
|
||||
}
|
||||
|
||||
private void printPrelim()
|
||||
@@ -156,21 +159,24 @@ namespace AaxDecrypter
|
||||
|
||||
public void SetOutputFilename(string outFileName)
|
||||
{
|
||||
this.outputFileName = outFileName;
|
||||
outputFileName = outFileName;
|
||||
|
||||
if (Path.GetExtension(this.outputFileName) != ".m4b")
|
||||
this.outputFileName = outputFileWithNewExt(".m4b");
|
||||
if (Path.GetExtension(outputFileName) != ".m4b")
|
||||
outputFileName = outputFileWithNewExt(".m4b");
|
||||
|
||||
this.outDir = Path.GetDirectoryName(this.outputFileName);
|
||||
if (File.Exists(outputFileName))
|
||||
File.Delete(outputFileName);
|
||||
|
||||
outDir = Path.GetDirectoryName(outputFileName);
|
||||
}
|
||||
|
||||
private string outputFileWithNewExt(string extension)
|
||||
=> Path.Combine(this.outDir, Path.GetFileNameWithoutExtension(this.outputFileName) + '.' + extension.Trim('.'));
|
||||
=> Path.Combine(outDir, Path.GetFileNameWithoutExtension(outputFileName) + '.' + extension.Trim('.'));
|
||||
|
||||
public bool Step1_CreateDir()
|
||||
{
|
||||
ProcessRunner.WorkingDir = this.outDir;
|
||||
Directory.CreateDirectory(this.outDir);
|
||||
ProcessRunner.WorkingDir = outDir;
|
||||
Directory.CreateDirectory(outDir);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -178,7 +184,7 @@ namespace AaxDecrypter
|
||||
{
|
||||
DecryptProgressUpdate?.Invoke(this, 0);
|
||||
|
||||
var tempRipFile = Path.Combine(this.outDir, "funny.aac");
|
||||
var tempRipFile = Path.Combine(outDir, "funny.aac");
|
||||
|
||||
var fail = "WARNING-Decrypt failure. ";
|
||||
|
||||
@@ -193,7 +199,7 @@ namespace AaxDecrypter
|
||||
if (returnCode == -99)
|
||||
{
|
||||
Console.WriteLine($"{fail}Incorrect decrypt key: {decryptKey}");
|
||||
this.decryptKey = null;
|
||||
decryptKey = null;
|
||||
returnCode = getKey_decrypt(tempRipFile);
|
||||
}
|
||||
}
|
||||
@@ -232,7 +238,7 @@ namespace AaxDecrypter
|
||||
|
||||
Console.WriteLine("Cracking activation bytes");
|
||||
var activation_bytes = BytesCracker.GetActivationBytes(checksum);
|
||||
this.decryptKey = activation_bytes;
|
||||
decryptKey = activation_bytes;
|
||||
Console.WriteLine("Activation bytes cracked. Decrypt key: " + activation_bytes);
|
||||
}
|
||||
|
||||
@@ -243,10 +249,10 @@ namespace AaxDecrypter
|
||||
Console.WriteLine("Decrypting with key " + decryptKey);
|
||||
|
||||
var returnCode = 100;
|
||||
var thread = new Thread(() => returnCode = this.ngDecrypt());
|
||||
var thread = new Thread(() => returnCode = ngDecrypt());
|
||||
thread.Start();
|
||||
|
||||
double fileLen = new FileInfo(this.inputFileName).Length;
|
||||
double fileLen = new FileInfo(inputFileName).Length;
|
||||
while (thread.IsAlive && returnCode == 100)
|
||||
{
|
||||
Thread.Sleep(500);
|
||||
@@ -266,7 +272,7 @@ namespace AaxDecrypter
|
||||
var info = new ProcessStartInfo
|
||||
{
|
||||
FileName = DecryptSupportLibraries.mp4trackdumpPath,
|
||||
Arguments = "-c " + this.encodingInfo.channels + " -r " + this.encodingInfo.sampleRate + " \"" + this.inputFileName + "\""
|
||||
Arguments = "-c " + encodingInfo.channels + " -r " + encodingInfo.sampleRate + " \"" + inputFileName + "\""
|
||||
};
|
||||
info.EnvironmentVariables["VARIABLE"] = decryptKey;
|
||||
|
||||
@@ -279,21 +285,22 @@ namespace AaxDecrypter
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
// temp file names for steps 3, 4, 5
|
||||
string tempChapsPath => Path.Combine(this.outDir, "tempChaps.mp4");
|
||||
// temp file names for steps 3, 4, 5
|
||||
string tempChapsGuid { get; } = Guid.NewGuid().ToString().ToUpper().Replace("-", "");
|
||||
string tempChapsPath => Path.Combine(outDir, $"tempChaps_{tempChapsGuid}.mp4");
|
||||
string mp4_file => outputFileWithNewExt(".mp4");
|
||||
string ff_txt_file => mp4_file + ".ff.txt";
|
||||
|
||||
public bool Step3_Chapterize()
|
||||
{
|
||||
string str1 = "";
|
||||
if (this.chapters.FirstChapterStart != 0.0)
|
||||
if (chapters.FirstChapterStart != 0.0)
|
||||
{
|
||||
str1 = " -ss " + this.chapters.FirstChapterStart.ToString("0.000", CultureInfo.InvariantCulture) + " -t " + (this.chapters.LastChapterStart - 1.0).ToString("0.000", CultureInfo.InvariantCulture) + " ";
|
||||
str1 = " -ss " + chapters.FirstChapterStart.ToString("0.000", CultureInfo.InvariantCulture) + " -t " + (chapters.LastChapterStart - 1.0).ToString("0.000", CultureInfo.InvariantCulture) + " ";
|
||||
}
|
||||
|
||||
string ffmpegTags = this.tags.GenerateFfmpegTags();
|
||||
string ffmpegChapters = this.chapters.GenerateFfmpegChapters();
|
||||
string ffmpegTags = tags.GenerateFfmpegTags();
|
||||
string ffmpegChapters = chapters.GenerateFfmpegChapters();
|
||||
File.WriteAllText(ff_txt_file, ffmpegTags + ffmpegChapters);
|
||||
|
||||
var tagAndChapterInfo = new ProcessStartInfo
|
||||
@@ -309,8 +316,8 @@ namespace AaxDecrypter
|
||||
public bool Step4_InsertCoverArt()
|
||||
{
|
||||
// save cover image as temp file
|
||||
var coverPath = Path.Combine(this.outDir, "cover-" + Guid.NewGuid() + ".jpg");
|
||||
FileExt.CreateFile(coverPath, this.coverBytes);
|
||||
var coverPath = Path.Combine(outDir, "cover-" + Guid.NewGuid() + ".jpg");
|
||||
FileExt.CreateFile(coverPath, coverBytes);
|
||||
|
||||
var insertCoverArtInfo = new ProcessStartInfo
|
||||
{
|
||||
@@ -329,26 +336,26 @@ namespace AaxDecrypter
|
||||
{
|
||||
FileExt.SafeDelete(mp4_file);
|
||||
FileExt.SafeDelete(ff_txt_file);
|
||||
FileExt.SafeMove(tempChapsPath, this.outputFileName);
|
||||
FileExt.SafeMove(tempChapsPath, outputFileName);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Step6_AddTags()
|
||||
{
|
||||
this.tags.AddAppleTags(this.outputFileName);
|
||||
tags.AddAppleTags(outputFileName);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool End_CreateCue()
|
||||
{
|
||||
File.WriteAllText(outputFileWithNewExt(".cue"), this.chapters.GetCuefromChapters(Path.GetFileName(this.outputFileName)));
|
||||
File.WriteAllText(outputFileWithNewExt(".cue"), chapters.GetCuefromChapters(Path.GetFileName(outputFileName)));
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool End_CreateNfo()
|
||||
{
|
||||
File.WriteAllText(outputFileWithNewExt(".nfo"), NFO.CreateNfoContents(AppName, this.tags, this.encodingInfo, this.chapters));
|
||||
File.WriteAllText(outputFileWithNewExt(".nfo"), NFO.CreateNfoContents(AppName, tags, encodingInfo, chapters));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace AaxDecrypter
|
||||
using TagLib.File tagLibFile = TagLib.File.Create(file, "audio/mp4", ReadStyle.Average);
|
||||
this.title = tagLibFile.Tag.Title.Replace(" (Unabridged)", "");
|
||||
this.album = tagLibFile.Tag.Album.Replace(" (Unabridged)", "");
|
||||
this.author = tagLibFile.Tag.FirstPerformer;
|
||||
this.author = tagLibFile.Tag.FirstPerformer ?? "[unknown]";
|
||||
this.year = tagLibFile.Tag.Year.ToString();
|
||||
this.comments = tagLibFile.Tag.Comment;
|
||||
this.duration = tagLibFile.Properties.Duration;
|
||||
|
||||
16
ApplicationServices/UNTESTED/DbContexts.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using DataLayer;
|
||||
using FileManager;
|
||||
|
||||
namespace ApplicationServices
|
||||
{
|
||||
public static class DbContexts
|
||||
{
|
||||
//// idea for future command/query separation
|
||||
// public static LibationContext GetCommandContext() { }
|
||||
// public static LibationContext GetQueryContext() { }
|
||||
|
||||
public static LibationContext GetContext()
|
||||
=> LibationContext.Create(SqliteStorage.ConnectionString);
|
||||
}
|
||||
}
|
||||
@@ -9,30 +9,51 @@ namespace ApplicationServices
|
||||
{
|
||||
public static class LibraryCommands
|
||||
{
|
||||
public static async Task<(int totalCount, int newCount)> IndexLibraryAsync(ILoginCallback callback)
|
||||
public static async Task<(int totalCount, int newCount)> ImportLibraryAsync(ILoginCallback callback)
|
||||
{
|
||||
var audibleApiActions = new AudibleApiActions();
|
||||
var items = await audibleApiActions.GetAllLibraryItemsAsync(callback);
|
||||
var totalCount = items.Count;
|
||||
try
|
||||
{
|
||||
var audibleApiActions = new AudibleApiActions();
|
||||
var items = await audibleApiActions.GetAllLibraryItemsAsync(callback);
|
||||
var totalCount = items.Count;
|
||||
Serilog.Log.Logger.Information($"GetAllLibraryItems: Total count {totalCount}");
|
||||
|
||||
var libImporter = new LibraryImporter();
|
||||
var newCount = await Task.Run(() => libImporter.Import(items));
|
||||
using var context = DbContexts.GetContext();
|
||||
var libImporter = new LibraryImporter(context);
|
||||
var newCount = await Task.Run(() => libImporter.Import(items));
|
||||
context.SaveChanges();
|
||||
Serilog.Log.Logger.Information($"Import: New count {newCount}");
|
||||
|
||||
await Task.Run(() => SearchEngineCommands.FullReIndex());
|
||||
await Task.Run(() => SearchEngineCommands.FullReIndex());
|
||||
Serilog.Log.Logger.Information("FullReIndex: success");
|
||||
|
||||
return (totalCount, newCount);
|
||||
return (totalCount, newCount);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Serilog.Log.Logger.Error(ex, "Error importing library");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public static int UpdateTags(this LibationContext context, Book book, string newTags)
|
||||
{
|
||||
book.UserDefinedItem.Tags = newTags;
|
||||
try
|
||||
{
|
||||
book.UserDefinedItem.Tags = newTags;
|
||||
|
||||
var qtyChanges = context.SaveChanges();
|
||||
var qtyChanges = context.SaveChanges();
|
||||
|
||||
if (qtyChanges > 0)
|
||||
SearchEngineCommands.UpdateBookTags(book);
|
||||
if (qtyChanges > 0)
|
||||
SearchEngineCommands.UpdateBookTags(book);
|
||||
|
||||
return qtyChanges;
|
||||
return qtyChanges;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Serilog.Log.Logger.Error(ex, "Error updating tags");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using DataLayer;
|
||||
using System.IO;
|
||||
using DataLayer;
|
||||
using LibationSearchEngine;
|
||||
|
||||
namespace ApplicationServices
|
||||
@@ -7,18 +8,18 @@ namespace ApplicationServices
|
||||
{
|
||||
public static void FullReIndex()
|
||||
{
|
||||
var engine = new SearchEngine();
|
||||
var engine = new SearchEngine(DbContexts.GetContext());
|
||||
engine.CreateNewIndex();
|
||||
}
|
||||
|
||||
public static SearchResultSet Search(string searchString)
|
||||
{
|
||||
var engine = new SearchEngine();
|
||||
var engine = new SearchEngine(DbContexts.GetContext());
|
||||
try
|
||||
{
|
||||
return engine.Search(searchString);
|
||||
}
|
||||
catch (System.IO.FileNotFoundException)
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
FullReIndex();
|
||||
return engine.Search(searchString);
|
||||
@@ -27,12 +28,12 @@ namespace ApplicationServices
|
||||
|
||||
public static void UpdateBookTags(Book book)
|
||||
{
|
||||
var engine = new SearchEngine();
|
||||
var engine = new SearchEngine(DbContexts.GetContext());
|
||||
try
|
||||
{
|
||||
engine.UpdateTags(book.AudibleProductId, book.UserDefinedItem.Tags);
|
||||
}
|
||||
catch (System.IO.FileNotFoundException)
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
FullReIndex();
|
||||
engine.UpdateTags(book.AudibleProductId, book.UserDefinedItem.Tags);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netcoreapp3.0;netstandard2.1</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1;netstandard2.1</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
@@ -12,13 +12,13 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.0.0">
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.0.0">
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.1.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
@@ -32,7 +32,6 @@
|
||||
<ItemGroup>
|
||||
<None Update="appsettings.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -123,16 +123,10 @@ namespace DataLayer
|
||||
ArgumentValidator.EnsureEnumerableNotNullOrEmpty(newContributors, nameof(newContributors));
|
||||
|
||||
// the edge cases of doing local-loaded vs remote-only got weird. just load it
|
||||
if (_contributorsLink == null)
|
||||
{
|
||||
ArgumentValidator.EnsureNotNull(context, nameof(context));
|
||||
if (!context.Entry(this).IsKeySet)
|
||||
throw new InvalidOperationException("Could not add contributors");
|
||||
if (_contributorsLink is null)
|
||||
getEntry(context).Collection(s => s.ContributorsLink).Load();
|
||||
|
||||
context.Entry(this).Collection(s => s.ContributorsLink).Load();
|
||||
}
|
||||
|
||||
var roleContributions = getContributions(role);
|
||||
var roleContributions = getContributions(role);
|
||||
var isIdentical = roleContributions.Select(c => c.Contributor).SequenceEqual(newContributors);
|
||||
if (isIdentical)
|
||||
return;
|
||||
@@ -140,7 +134,8 @@ namespace DataLayer
|
||||
_contributorsLink.RemoveWhere(bc => bc.Role == role);
|
||||
addNewContributors(newContributors, role);
|
||||
}
|
||||
private void addNewContributors(IEnumerable<Contributor> newContributors, Role role)
|
||||
|
||||
private void addNewContributors(IEnumerable<Contributor> newContributors, Role role)
|
||||
{
|
||||
byte order = 0;
|
||||
var newContributionsEnum = newContributors.Select(c => new BookContributor(this, c, role, order++));
|
||||
@@ -155,6 +150,18 @@ namespace DataLayer
|
||||
.ToList();
|
||||
#endregion
|
||||
|
||||
private Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry<Book> getEntry(DbContext context)
|
||||
{
|
||||
ArgumentValidator.EnsureNotNull(context, nameof(context));
|
||||
|
||||
var entry = context.Entry(this);
|
||||
|
||||
if (!entry.IsKeySet)
|
||||
throw new InvalidOperationException("Could not load a valid Book from database");
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
#region series
|
||||
private HashSet<SeriesBook> _seriesLink;
|
||||
public IEnumerable<SeriesBook> SeriesLink => _seriesLink?.ToList();
|
||||
@@ -186,16 +193,10 @@ namespace DataLayer
|
||||
|
||||
// our add() is conditional upon what's already included in the collection.
|
||||
// therefore if not loaded, a trip is required. might as well just load it
|
||||
if (_seriesLink == null)
|
||||
{
|
||||
ArgumentValidator.EnsureNotNull(context, nameof(context));
|
||||
if (!context.Entry(this).IsKeySet)
|
||||
throw new InvalidOperationException("Could not add series");
|
||||
if (_seriesLink is null)
|
||||
getEntry(context).Collection(s => s.SeriesLink).Load();
|
||||
|
||||
context.Entry(this).Collection(s => s.SeriesLink).Load();
|
||||
}
|
||||
|
||||
var singleSeriesBook = _seriesLink.SingleOrDefault(sb => sb.Series == series);
|
||||
var singleSeriesBook = _seriesLink.SingleOrDefault(sb => sb.Series == series);
|
||||
if (singleSeriesBook == null)
|
||||
_seriesLink.Add(new SeriesBook(series, this, index));
|
||||
else
|
||||
@@ -211,8 +212,7 @@ namespace DataLayer
|
||||
public void AddSupplementDownloadUrl(string url)
|
||||
{
|
||||
// supplements are owned by Book, so no need to Load():
|
||||
// OwnsMany: "Can only ever appear on navigation properties of other entity types.
|
||||
// Are automatically loaded, and can only be tracked by a DbContext alongside their owner."
|
||||
// Are automatically loaded, and can only be tracked by a DbContext alongside their owner.
|
||||
|
||||
ArgumentValidator.EnsureNotNullOrWhiteSpace(url, nameof(url));
|
||||
|
||||
@@ -232,19 +232,12 @@ namespace DataLayer
|
||||
}
|
||||
|
||||
public void UpdateCategory(Category category, DbContext context = null)
|
||||
{
|
||||
// since category is never null, nullity means it hasn't been loaded. non null means we're correctly loaded. just overwrite
|
||||
if (Category != null)
|
||||
{
|
||||
Category = category;
|
||||
return;
|
||||
}
|
||||
{
|
||||
// since category is never null, nullity means it hasn't been loaded
|
||||
if (Category is null)
|
||||
getEntry(context).Reference(s => s.Category).Load();
|
||||
|
||||
if (context == null)
|
||||
throw new Exception("need context");
|
||||
|
||||
context.Entry(this).Reference(s => s.Category).Load();
|
||||
Category = category;
|
||||
Category = category;
|
||||
}
|
||||
|
||||
public override string ToString() => $"[{AudibleProductId}] {Title}";
|
||||
|
||||
@@ -25,10 +25,10 @@ namespace DataLayer
|
||||
public DbSet<Series> Series { get; private set; }
|
||||
public DbSet<Category> Categories { get; private set; }
|
||||
|
||||
public static LibationContext Create()
|
||||
public static LibationContext Create(string connectionString)
|
||||
{
|
||||
var factory = new LibationContextFactory();
|
||||
var context = factory.Create();
|
||||
var context = factory.Create(connectionString);
|
||||
return context;
|
||||
}
|
||||
|
||||
@@ -64,7 +64,8 @@ namespace DataLayer
|
||||
.Entity<Contributor>()
|
||||
.HasData(Contributor.GetEmpty());
|
||||
|
||||
// views are now supported via "query types" (instead of "entity types"): https://docs.microsoft.com/en-us/ef/core/modeling/query-types
|
||||
}
|
||||
}
|
||||
// views are now supported via "keyless entity types" (instead of "entity types" or the prev "query types"):
|
||||
// https://docs.microsoft.com/en-us/ef/core/modeling/keyless-entity-types
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,14 +8,11 @@ namespace DataLayer
|
||||
{
|
||||
public static class BookQueries
|
||||
{
|
||||
public static Book GetBook_Flat_NoTracking(string productId)
|
||||
{
|
||||
using var context = LibationContext.Create();
|
||||
return context
|
||||
public static Book GetBook_Flat_NoTracking(this LibationContext context, string productId)
|
||||
=> context
|
||||
.Books
|
||||
.AsNoTracking()
|
||||
.GetBook(productId);
|
||||
}
|
||||
|
||||
public static Book GetBook(this IQueryable<Book> books, string productId)
|
||||
=> books
|
||||
|
||||
@@ -12,24 +12,18 @@ namespace DataLayer
|
||||
.GetLibrary()
|
||||
.ToList();
|
||||
|
||||
public static List<LibraryBook> GetLibrary_Flat_NoTracking()
|
||||
{
|
||||
using var context = LibationContext.Create();
|
||||
return context
|
||||
public static List<LibraryBook> GetLibrary_Flat_NoTracking(this LibationContext context)
|
||||
=> context
|
||||
.Library
|
||||
.AsNoTracking()
|
||||
.GetLibrary()
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public static LibraryBook GetLibraryBook_Flat_NoTracking(string productId)
|
||||
{
|
||||
using var context = LibationContext.Create();
|
||||
return context
|
||||
public static LibraryBook GetLibraryBook_Flat_NoTracking(this LibationContext context, string productId)
|
||||
=> context
|
||||
.Library
|
||||
.AsNoTracking()
|
||||
.GetLibraryBook(productId);
|
||||
}
|
||||
.GetLibraryBook(productId);
|
||||
|
||||
/// <summary>This is still IQueryable. YOU MUST CALL ToList() YOURSELF</summary>
|
||||
public static IQueryable<LibraryBook> GetLibrary(this IQueryable<LibraryBook> library)
|
||||
|
||||
@@ -4,7 +4,6 @@ using System.Linq;
|
||||
using Dinah.Core.Collections.Generic;
|
||||
using Dinah.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||||
|
||||
namespace DataLayer
|
||||
{
|
||||
@@ -14,25 +13,18 @@ namespace DataLayer
|
||||
|
||||
public void Executing(DbContext context)
|
||||
{
|
||||
// persist tags:
|
||||
var modifiedEntities = context
|
||||
var tagsCollection
|
||||
= context
|
||||
.ChangeTracker
|
||||
.Entries()
|
||||
.Where(p => p.State.In(EntityState.Modified, EntityState.Added))
|
||||
.ToList();
|
||||
|
||||
persistTags(modifiedEntities);
|
||||
}
|
||||
|
||||
private static void persistTags(List<EntityEntry> modifiedEntities)
|
||||
{
|
||||
var tagSets = modifiedEntities
|
||||
.Where(e => e.State.In(EntityState.Modified, EntityState.Added))
|
||||
.Select(e => e.Entity as UserDefinedItem)
|
||||
// filter by null but NOT by blank. blank is the valid way to show the absence of tags
|
||||
.Where(a => a != null)
|
||||
.Where(udi => udi != null)
|
||||
// do NOT filter out entires with blank tags. blank is the valid way to show the absence of tags
|
||||
.Select(t => (t.Book.AudibleProductId, t.Tags))
|
||||
.ToList();
|
||||
foreach (var t in tagSets)
|
||||
FileManager.TagsPersistence.Save(t.Book.AudibleProductId, t.Tags);
|
||||
|
||||
FileManager.TagsPersistence.Save(tagsCollection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,15 +7,22 @@ nuget
|
||||
Microsoft.EntityFrameworkCore.Tools (needed for using Package Manager Console)
|
||||
Microsoft.EntityFrameworkCore.Sqlite
|
||||
|
||||
MIGRATIONS require standard, not core
|
||||
using standard instead of core. edit 3 things in csproj
|
||||
1of3: pluralize xml TargetFramework tag to TargetFrameworks
|
||||
2of2: TargetFrameworks from: netstandard2.1
|
||||
to: netcoreapp3.0;netstandard2.1
|
||||
3of3: add
|
||||
<PropertyGroup>
|
||||
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
|
||||
</PropertyGroup>
|
||||
MIGRATIONS
|
||||
require core, not standard
|
||||
this can be a problem b/c standard and framework can only reference standard, not core
|
||||
TO USE MIGRATIONS (core and/or standard)
|
||||
add to csproj
|
||||
<PropertyGroup>
|
||||
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
|
||||
</PropertyGroup>
|
||||
TO USE MIGRATIONS AS *BOTH* CORE AND STANDARD
|
||||
edit csproj
|
||||
pluralize this xml tag
|
||||
from: TargetFramework
|
||||
to: TargetFrameworks
|
||||
inside of TargetFrameworks
|
||||
from: netstandard2.1
|
||||
to: netcoreapp3.1;netstandard2.1
|
||||
|
||||
run. error
|
||||
SQLite Error 1: 'no such table: Blogs'.
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
{
|
||||
"ConnectionStrings": {
|
||||
"LibationContext_sqlserver": "Server=(LocalDb)\\MSSQLLocalDB;Database=DataLayer.LibationContext;Integrated Security=true;",
|
||||
|
||||
"// this connection string is ONLY used for DataLayer's Migrations. this appsettings.json file is NOT used at all by application; it is overwritten": "",
|
||||
"LibationContext": "Data Source=LibationContext.db;Foreign Keys=False;",
|
||||
|
||||
"// on windows sqlite paths accept windows and/or unix slashes": "",
|
||||
"// sqlite notes": "",
|
||||
"// absolute path example": "Data Source=C:/foo/bar/sample.db",
|
||||
"// relative path example": "Data Source=sample.db",
|
||||
"// on windows: sqlite paths accept windows and/or unix slashes": "",
|
||||
"MyTestContext": "Data Source=%DESKTOP%/sample.db"
|
||||
}
|
||||
}
|
||||
@@ -9,29 +9,31 @@ namespace DtoImporterService
|
||||
{
|
||||
public class BookImporter : ItemsImporterBase
|
||||
{
|
||||
public BookImporter(LibationContext context) : base(context) { }
|
||||
|
||||
public override IEnumerable<Exception> Validate(IEnumerable<Item> items) => new BookValidator().Validate(items);
|
||||
|
||||
protected override int DoImport(IEnumerable<Item> items, LibationContext context)
|
||||
protected override int DoImport(IEnumerable<Item> items)
|
||||
{
|
||||
// pre-req.s
|
||||
new ContributorImporter().Import(items, context);
|
||||
new SeriesImporter().Import(items, context);
|
||||
new CategoryImporter().Import(items, context);
|
||||
new ContributorImporter(DbContext).Import(items);
|
||||
new SeriesImporter(DbContext).Import(items);
|
||||
new CategoryImporter(DbContext).Import(items);
|
||||
|
||||
// get distinct
|
||||
var productIds = items.Select(i => i.ProductId).ToList();
|
||||
|
||||
// load db existing => .Local
|
||||
loadLocal_books(productIds, context);
|
||||
loadLocal_books(productIds);
|
||||
|
||||
// upsert
|
||||
var qtyNew = upsertBooks(items, context);
|
||||
var qtyNew = upsertBooks(items);
|
||||
return qtyNew;
|
||||
}
|
||||
|
||||
private void loadLocal_books(List<string> productIds, LibationContext context)
|
||||
private void loadLocal_books(List<string> productIds)
|
||||
{
|
||||
var localProductIds = context.Books.Local.Select(b => b.AudibleProductId);
|
||||
var localProductIds = DbContext.Books.Local.Select(b => b.AudibleProductId);
|
||||
var remainingProductIds = productIds
|
||||
.Distinct()
|
||||
.Except(localProductIds)
|
||||
@@ -39,29 +41,29 @@ namespace DtoImporterService
|
||||
|
||||
// GetBooks() eager loads Series, category, et al
|
||||
if (remainingProductIds.Any())
|
||||
context.Books.GetBooks(b => remainingProductIds.Contains(b.AudibleProductId)).ToList();
|
||||
DbContext.Books.GetBooks(b => remainingProductIds.Contains(b.AudibleProductId)).ToList();
|
||||
}
|
||||
|
||||
private int upsertBooks(IEnumerable<Item> items, LibationContext context)
|
||||
private int upsertBooks(IEnumerable<Item> items)
|
||||
{
|
||||
var qtyNew = 0;
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
var book = context.Books.Local.SingleOrDefault(p => p.AudibleProductId == item.ProductId);
|
||||
var book = DbContext.Books.Local.SingleOrDefault(p => p.AudibleProductId == item.ProductId);
|
||||
if (book is null)
|
||||
{
|
||||
book = createNewBook(item, context);
|
||||
book = createNewBook(item);
|
||||
qtyNew++;
|
||||
}
|
||||
|
||||
updateBook(item, book, context);
|
||||
updateBook(item, book);
|
||||
}
|
||||
|
||||
return qtyNew;
|
||||
}
|
||||
|
||||
private static Book createNewBook(Item item, LibationContext context)
|
||||
private Book createNewBook(Item item)
|
||||
{
|
||||
// absence of authors is very rare, but possible
|
||||
if (!item.Authors?.Any() ?? true)
|
||||
@@ -70,7 +72,7 @@ namespace DtoImporterService
|
||||
// nested logic is required so order of names is retained. else, contributors may appear in the order they were inserted into the db
|
||||
var authors = item
|
||||
.Authors
|
||||
.Select(a => context.Contributors.Local.Single(c => a.Name == c.Name))
|
||||
.Select(a => DbContext.Contributors.Local.Single(c => a.Name == c.Name))
|
||||
.ToList();
|
||||
|
||||
var narrators
|
||||
@@ -80,15 +82,15 @@ namespace DtoImporterService
|
||||
// nested logic is required so order of names is retained. else, contributors may appear in the order they were inserted into the db
|
||||
: item
|
||||
.Narrators
|
||||
.Select(n => context.Contributors.Local.Single(c => n.Name == c.Name))
|
||||
.Select(n => DbContext.Contributors.Local.Single(c => n.Name == c.Name))
|
||||
.ToList();
|
||||
|
||||
// categories are laid out for a breadcrumb. category is 1st, subcategory is 2nd
|
||||
// absence of categories is very rare, but possible
|
||||
var lastCategory = item.Categories.LastOrDefault()?.CategoryId ?? "";
|
||||
var category = context.Categories.Local.SingleOrDefault(c => c.AudibleCategoryId == lastCategory);
|
||||
var category = DbContext.Categories.Local.SingleOrDefault(c => c.AudibleCategoryId == lastCategory);
|
||||
|
||||
var book = context.Books.Add(new Book(
|
||||
var book = DbContext.Books.Add(new Book(
|
||||
new AudibleProductId(item.ProductId),
|
||||
item.Title,
|
||||
item.Description,
|
||||
@@ -101,7 +103,7 @@ namespace DtoImporterService
|
||||
var publisherName = item.Publisher;
|
||||
if (!string.IsNullOrWhiteSpace(publisherName))
|
||||
{
|
||||
var publisher = context.Contributors.Local.Single(c => publisherName == c.Name);
|
||||
var publisher = DbContext.Contributors.Local.Single(c => publisherName == c.Name);
|
||||
book.ReplacePublisher(publisher);
|
||||
}
|
||||
|
||||
@@ -113,7 +115,7 @@ namespace DtoImporterService
|
||||
return book;
|
||||
}
|
||||
|
||||
private static void updateBook(Item item, Book book, LibationContext context)
|
||||
private void updateBook(Item item, Book book)
|
||||
{
|
||||
// set/update book-specific info which may have changed
|
||||
book.PictureId = item.PictureId;
|
||||
@@ -128,7 +130,7 @@ namespace DtoImporterService
|
||||
{
|
||||
foreach (var seriesEntry in item.Series)
|
||||
{
|
||||
var series = context.Series.Local.Single(s => seriesEntry.SeriesId == s.AudibleSeriesId);
|
||||
var series = DbContext.Series.Local.Single(s => seriesEntry.SeriesId == s.AudibleSeriesId);
|
||||
book.UpsertSeries(series, seriesEntry.Index);
|
||||
}
|
||||
}
|
||||
@@ -9,25 +9,27 @@ namespace DtoImporterService
|
||||
{
|
||||
public class CategoryImporter : ItemsImporterBase
|
||||
{
|
||||
public CategoryImporter(LibationContext context) : base(context) { }
|
||||
|
||||
public override IEnumerable<Exception> Validate(IEnumerable<Item> items) => new CategoryValidator().Validate(items);
|
||||
|
||||
protected override int DoImport(IEnumerable<Item> items, LibationContext context)
|
||||
protected override int DoImport(IEnumerable<Item> items)
|
||||
{
|
||||
// get distinct
|
||||
var categoryIds = items.GetCategoriesDistinct().Select(c => c.CategoryId).ToList();
|
||||
|
||||
// load db existing => .Local
|
||||
loadLocal_categories(categoryIds, context);
|
||||
loadLocal_categories(categoryIds);
|
||||
|
||||
// upsert
|
||||
var categoryPairs = items.GetCategoryPairsDistinct().ToList();
|
||||
var qtyNew = upsertCategories(categoryPairs, context);
|
||||
var qtyNew = upsertCategories(categoryPairs);
|
||||
return qtyNew;
|
||||
}
|
||||
|
||||
private void loadLocal_categories(List<string> categoryIds, LibationContext context)
|
||||
private void loadLocal_categories(List<string> categoryIds)
|
||||
{
|
||||
var localIds = context.Categories.Local.Select(c => c.AudibleCategoryId);
|
||||
var localIds = DbContext.Categories.Local.Select(c => c.AudibleCategoryId);
|
||||
var remainingCategoryIds = categoryIds
|
||||
.Distinct()
|
||||
.Except(localIds)
|
||||
@@ -37,11 +39,11 @@ namespace DtoImporterService
|
||||
// remember to include default/empty/missing
|
||||
var emptyName = Contributor.GetEmpty().Name;
|
||||
if (remainingCategoryIds.Any())
|
||||
context.Categories.Where(c => remainingCategoryIds.Contains(c.AudibleCategoryId) || c.Name == emptyName).ToList();
|
||||
DbContext.Categories.Where(c => remainingCategoryIds.Contains(c.AudibleCategoryId) || c.Name == emptyName).ToList();
|
||||
}
|
||||
|
||||
// only use after loading contributors => local
|
||||
private int upsertCategories(List<Ladder[]> categoryPairs, LibationContext context)
|
||||
private int upsertCategories(List<Ladder[]> categoryPairs)
|
||||
{
|
||||
var qtyNew = 0;
|
||||
|
||||
@@ -54,12 +56,12 @@ namespace DtoImporterService
|
||||
|
||||
Category parentCategory = null;
|
||||
if (i == 1)
|
||||
parentCategory = context.Categories.Local.Single(c => c.AudibleCategoryId == pair[0].CategoryId);
|
||||
parentCategory = DbContext.Categories.Local.Single(c => c.AudibleCategoryId == pair[0].CategoryId);
|
||||
|
||||
var category = context.Categories.Local.SingleOrDefault(c => c.AudibleCategoryId == id);
|
||||
var category = DbContext.Categories.Local.SingleOrDefault(c => c.AudibleCategoryId == id);
|
||||
if (category is null)
|
||||
{
|
||||
category = context.Categories.Add(new Category(new AudibleCategoryId(id), name)).Entity;
|
||||
category = DbContext.Categories.Add(new Category(new AudibleCategoryId(id), name)).Entity;
|
||||
qtyNew++;
|
||||
}
|
||||
|
||||
@@ -9,9 +9,11 @@ namespace DtoImporterService
|
||||
{
|
||||
public class ContributorImporter : ItemsImporterBase
|
||||
{
|
||||
public ContributorImporter(LibationContext context) : base(context) { }
|
||||
|
||||
public override IEnumerable<Exception> Validate(IEnumerable<Item> items) => new ContributorValidator().Validate(items);
|
||||
|
||||
protected override int DoImport(IEnumerable<Item> items, LibationContext context)
|
||||
protected override int DoImport(IEnumerable<Item> items)
|
||||
{
|
||||
// get distinct
|
||||
var authors = items.GetAuthorsDistinct().ToList();
|
||||
@@ -24,23 +26,23 @@ namespace DtoImporterService
|
||||
.Union(narrators.Select(n => n.Name))
|
||||
.Where(name => !string.IsNullOrWhiteSpace(name))
|
||||
.ToList();
|
||||
loadLocal_contributors(allNames, context);
|
||||
loadLocal_contributors(allNames);
|
||||
|
||||
// upsert
|
||||
var qtyNew = 0;
|
||||
qtyNew += upsertPeople(authors, context);
|
||||
qtyNew += upsertPeople(narrators, context);
|
||||
qtyNew += upsertPublishers(publishers, context);
|
||||
qtyNew += upsertPeople(authors);
|
||||
qtyNew += upsertPeople(narrators);
|
||||
qtyNew += upsertPublishers(publishers);
|
||||
return qtyNew;
|
||||
}
|
||||
|
||||
private void loadLocal_contributors(List<string> contributorNames, LibationContext context)
|
||||
private void loadLocal_contributors(List<string> contributorNames)
|
||||
{
|
||||
//// BAD: very inefficient
|
||||
// var x = context.Contributors.Local.Where(c => !contribNames.Contains(c.Name));
|
||||
|
||||
// GOOD: Except() is efficient. Due to hashing, it's close to O(n)
|
||||
var localNames = context.Contributors.Local.Select(c => c.Name);
|
||||
var localNames = DbContext.Contributors.Local.Select(c => c.Name);
|
||||
var remainingContribNames = contributorNames
|
||||
.Distinct()
|
||||
.Except(localNames)
|
||||
@@ -50,20 +52,20 @@ namespace DtoImporterService
|
||||
// remember to include default/empty/missing
|
||||
var emptyName = Contributor.GetEmpty().Name;
|
||||
if (remainingContribNames.Any())
|
||||
context.Contributors.Where(c => remainingContribNames.Contains(c.Name) || c.Name == emptyName).ToList();
|
||||
DbContext.Contributors.Where(c => remainingContribNames.Contains(c.Name) || c.Name == emptyName).ToList();
|
||||
}
|
||||
|
||||
// only use after loading contributors => local
|
||||
private int upsertPeople(List<Person> people, LibationContext context)
|
||||
private int upsertPeople(List<Person> people)
|
||||
{
|
||||
var qtyNew = 0;
|
||||
|
||||
foreach (var p in people)
|
||||
{
|
||||
var person = context.Contributors.Local.SingleOrDefault(c => c.Name == p.Name);
|
||||
var person = DbContext.Contributors.Local.SingleOrDefault(c => c.Name == p.Name);
|
||||
if (person == null)
|
||||
{
|
||||
person = context.Contributors.Add(new Contributor(p.Name, p.Asin)).Entity;
|
||||
person = DbContext.Contributors.Add(new Contributor(p.Name, p.Asin)).Entity;
|
||||
qtyNew++;
|
||||
}
|
||||
}
|
||||
@@ -72,15 +74,15 @@ namespace DtoImporterService
|
||||
}
|
||||
|
||||
// only use after loading contributors => local
|
||||
private int upsertPublishers(List<string> publishers, LibationContext context)
|
||||
private int upsertPublishers(List<string> publishers)
|
||||
{
|
||||
var qtyNew = 0;
|
||||
|
||||
foreach (var publisherName in publishers)
|
||||
{
|
||||
if (context.Contributors.Local.SingleOrDefault(c => c.Name == publisherName) == null)
|
||||
if (DbContext.Contributors.Local.SingleOrDefault(c => c.Name == publisherName) == null)
|
||||
{
|
||||
context.Contributors.Add(new Contributor(publisherName));
|
||||
DbContext.Contributors.Add(new Contributor(publisherName));
|
||||
qtyNew++;
|
||||
}
|
||||
}
|
||||
@@ -3,23 +3,25 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using AudibleApiDTOs;
|
||||
using DataLayer;
|
||||
using Dinah.Core;
|
||||
|
||||
namespace DtoImporterService
|
||||
{
|
||||
public interface IContextRunner<T>
|
||||
public abstract class ImporterBase<T>
|
||||
{
|
||||
public TResult Run<TResult>(Func<T, LibationContext, TResult> func, T param, LibationContext context = null)
|
||||
{
|
||||
if (context is null)
|
||||
{
|
||||
using (context = LibationContext.Create())
|
||||
{
|
||||
var r = Run(func, param, context);
|
||||
context.SaveChanges();
|
||||
return r;
|
||||
}
|
||||
}
|
||||
protected LibationContext DbContext { get; }
|
||||
|
||||
public ImporterBase(LibationContext context)
|
||||
{
|
||||
ArgumentValidator.EnsureNotNull(context, nameof(context));
|
||||
DbContext = context;
|
||||
}
|
||||
|
||||
/// <summary>LONG RUNNING. call with await Task.Run</summary>
|
||||
public int Import(T param) => Run(DoImport, param);
|
||||
|
||||
public TResult Run<TResult>(Func<T, TResult> func, T param)
|
||||
{
|
||||
try
|
||||
{
|
||||
var exceptions = Validate(param);
|
||||
@@ -34,7 +36,7 @@ namespace DtoImporterService
|
||||
|
||||
try
|
||||
{
|
||||
var result = func(param, context);
|
||||
var result = func(param);
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -43,18 +45,13 @@ namespace DtoImporterService
|
||||
throw;
|
||||
}
|
||||
}
|
||||
IEnumerable<Exception> Validate(T param);
|
||||
}
|
||||
|
||||
public abstract class ImporterBase<T> : IContextRunner<T>
|
||||
{
|
||||
/// <summary>LONG RUNNING. call with await Task.Run</summary>
|
||||
public int Import(T param, LibationContext context = null)
|
||||
=> ((IContextRunner<T>)this).Run(DoImport, param, context);
|
||||
|
||||
protected abstract int DoImport(T elements, LibationContext context);
|
||||
protected abstract int DoImport(T elements);
|
||||
public abstract IEnumerable<Exception> Validate(T param);
|
||||
}
|
||||
|
||||
public abstract class ItemsImporterBase : ImporterBase<IEnumerable<Item>> { }
|
||||
public abstract class ItemsImporterBase : ImporterBase<IEnumerable<Item>>
|
||||
{
|
||||
public ItemsImporterBase(LibationContext context) : base(context) { }
|
||||
}
|
||||
}
|
||||
@@ -9,27 +9,29 @@ namespace DtoImporterService
|
||||
{
|
||||
public class LibraryImporter : ItemsImporterBase
|
||||
{
|
||||
public LibraryImporter(LibationContext context) : base(context) { }
|
||||
|
||||
public override IEnumerable<Exception> Validate(IEnumerable<Item> items) => new LibraryValidator().Validate(items);
|
||||
|
||||
protected override int DoImport(IEnumerable<Item> items, LibationContext context)
|
||||
protected override int DoImport(IEnumerable<Item> items)
|
||||
{
|
||||
new BookImporter().Import(items, context);
|
||||
new BookImporter(DbContext).Import(items);
|
||||
|
||||
var qtyNew = upsertLibraryBooks(items, context);
|
||||
var qtyNew = upsertLibraryBooks(items);
|
||||
return qtyNew;
|
||||
}
|
||||
|
||||
private int upsertLibraryBooks(IEnumerable<Item> items, LibationContext context)
|
||||
private int upsertLibraryBooks(IEnumerable<Item> items)
|
||||
{
|
||||
var currentLibraryProductIds = context.Library.Select(l => l.Book.AudibleProductId).ToList();
|
||||
var currentLibraryProductIds = DbContext.Library.Select(l => l.Book.AudibleProductId).ToList();
|
||||
var newItems = items.Where(dto => !currentLibraryProductIds.Contains(dto.ProductId)).ToList();
|
||||
|
||||
foreach (var newItem in newItems)
|
||||
{
|
||||
var libraryBook = new LibraryBook(
|
||||
context.Books.Local.Single(b => b.AudibleProductId == newItem.ProductId),
|
||||
DbContext.Books.Local.Single(b => b.AudibleProductId == newItem.ProductId),
|
||||
newItem.DateAdded);
|
||||
context.Library.Add(libraryBook);
|
||||
DbContext.Library.Add(libraryBook);
|
||||
}
|
||||
|
||||
var qtyNew = newItems.Count;
|
||||
@@ -9,44 +9,46 @@ namespace DtoImporterService
|
||||
{
|
||||
public class SeriesImporter : ItemsImporterBase
|
||||
{
|
||||
public SeriesImporter(LibationContext context) : base(context) { }
|
||||
|
||||
public override IEnumerable<Exception> Validate(IEnumerable<Item> items) => new SeriesValidator().Validate(items);
|
||||
|
||||
protected override int DoImport(IEnumerable<Item> items, LibationContext context)
|
||||
protected override int DoImport(IEnumerable<Item> items)
|
||||
{
|
||||
// get distinct
|
||||
var series = items.GetSeriesDistinct().ToList();
|
||||
|
||||
// load db existing => .Local
|
||||
loadLocal_series(series, context);
|
||||
loadLocal_series(series);
|
||||
|
||||
// upsert
|
||||
var qtyNew = upsertSeries(series, context);
|
||||
var qtyNew = upsertSeries(series);
|
||||
return qtyNew;
|
||||
}
|
||||
|
||||
private void loadLocal_series(List<AudibleApiDTOs.Series> series, LibationContext context)
|
||||
private void loadLocal_series(List<AudibleApiDTOs.Series> series)
|
||||
{
|
||||
var seriesIds = series.Select(s => s.SeriesId).ToList();
|
||||
var localIds = context.Series.Local.Select(s => s.AudibleSeriesId).ToList();
|
||||
var localIds = DbContext.Series.Local.Select(s => s.AudibleSeriesId).ToList();
|
||||
var remainingSeriesIds = seriesIds
|
||||
.Distinct()
|
||||
.Except(localIds)
|
||||
.ToList();
|
||||
|
||||
if (remainingSeriesIds.Any())
|
||||
context.Series.Where(s => remainingSeriesIds.Contains(s.AudibleSeriesId)).ToList();
|
||||
DbContext.Series.Where(s => remainingSeriesIds.Contains(s.AudibleSeriesId)).ToList();
|
||||
}
|
||||
|
||||
private int upsertSeries(List<AudibleApiDTOs.Series> requestedSeries, LibationContext context)
|
||||
private int upsertSeries(List<AudibleApiDTOs.Series> requestedSeries)
|
||||
{
|
||||
var qtyNew = 0;
|
||||
|
||||
foreach (var s in requestedSeries)
|
||||
{
|
||||
var series = context.Series.Local.SingleOrDefault(c => c.AudibleSeriesId == s.SeriesId);
|
||||
var series = DbContext.Series.Local.SingleOrDefault(c => c.AudibleSeriesId == s.SeriesId);
|
||||
if (series is null)
|
||||
{
|
||||
series = context.Series.Add(new DataLayer.Series(new AudibleSeriesId(s.SeriesId))).Entity;
|
||||
series = DbContext.Series.Add(new DataLayer.Series(new AudibleSeriesId(s.SeriesId))).Entity;
|
||||
qtyNew++;
|
||||
}
|
||||
series.UpdateName(s.SeriesName);
|
||||
@@ -17,9 +17,9 @@ namespace FileLiberator
|
||||
/// </summary>
|
||||
public class BackupBook : IProcessable
|
||||
{
|
||||
public event EventHandler<string> Begin;
|
||||
public event EventHandler<LibraryBook> Begin;
|
||||
public event EventHandler<string> StatusUpdate;
|
||||
public event EventHandler<string> Completed;
|
||||
public event EventHandler<LibraryBook> Completed;
|
||||
|
||||
public DownloadBook DownloadBook { get; } = new DownloadBook();
|
||||
public DecryptBook DecryptBook { get; } = new DecryptBook();
|
||||
@@ -32,10 +32,7 @@ namespace FileLiberator
|
||||
// often calls events which prints to forms in the UI context
|
||||
public async Task<StatusHandler> ProcessAsync(LibraryBook libraryBook)
|
||||
{
|
||||
var productId = libraryBook.Book.AudibleProductId;
|
||||
var displayMessage = $"[{productId}] {libraryBook.Book.Title}";
|
||||
|
||||
Begin?.Invoke(this, displayMessage);
|
||||
Begin?.Invoke(this, libraryBook);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -61,7 +58,7 @@ namespace FileLiberator
|
||||
}
|
||||
finally
|
||||
{
|
||||
Completed?.Invoke(this, displayMessage);
|
||||
Completed?.Invoke(this, libraryBook);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace FileLiberator
|
||||
/// </summary>
|
||||
public class DecryptBook : IDecryptable
|
||||
{
|
||||
public event EventHandler<string> Begin;
|
||||
public event EventHandler<LibraryBook> Begin;
|
||||
public event EventHandler<string> StatusUpdate;
|
||||
public event EventHandler<string> DecryptBegin;
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace FileLiberator
|
||||
public event EventHandler<int> UpdateProgress;
|
||||
|
||||
public event EventHandler<string> DecryptCompleted;
|
||||
public event EventHandler<string> Completed;
|
||||
public event EventHandler<LibraryBook> Completed;
|
||||
|
||||
public bool Validate(LibraryBook libraryBook)
|
||||
=> AudibleFileStorage.AAX.Exists(libraryBook.Book.AudibleProductId)
|
||||
@@ -42,9 +42,7 @@ namespace FileLiberator
|
||||
// often calls events which prints to forms in the UI context
|
||||
public async Task<StatusHandler> ProcessAsync(LibraryBook libraryBook)
|
||||
{
|
||||
var displayMessage = $"[{libraryBook.Book.AudibleProductId}] {libraryBook.Book.Title}";
|
||||
|
||||
Begin?.Invoke(this, displayMessage);
|
||||
Begin?.Invoke(this, libraryBook);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -52,7 +50,7 @@ namespace FileLiberator
|
||||
|
||||
if (aaxFilename == null)
|
||||
return new StatusHandler { "aaxFilename parameter is null" };
|
||||
if (!FileUtility.FileExists(aaxFilename))
|
||||
if (!File.Exists(aaxFilename))
|
||||
return new StatusHandler { $"Cannot find AAX file: {aaxFilename}" };
|
||||
if (AudibleFileStorage.Audio.Exists(libraryBook.Book.AudibleProductId))
|
||||
return new StatusHandler { "Cannot find decrypt. Final audio file already exists" };
|
||||
@@ -76,7 +74,7 @@ namespace FileLiberator
|
||||
}
|
||||
finally
|
||||
{
|
||||
Completed?.Invoke(this, displayMessage);
|
||||
Completed?.Invoke(this, libraryBook);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,17 +92,16 @@ namespace FileLiberator
|
||||
NarratorsDiscovered?.Invoke(this, converter.tags.narrator);
|
||||
CoverImageFilepathDiscovered?.Invoke(this, converter.coverBytes);
|
||||
|
||||
// override default which was set in CreateAsync
|
||||
converter.SetOutputFilename(proposedOutputFile);
|
||||
converter.DecryptProgressUpdate += (s, progress) => UpdateProgress?.Invoke(this, progress);
|
||||
|
||||
// REAL WORK DONE HERE
|
||||
var success = await Task.Run(() => converter.Run());
|
||||
|
||||
// decrypt failed
|
||||
if (!success)
|
||||
{
|
||||
Console.WriteLine("decrypt failed");
|
||||
return null;
|
||||
}
|
||||
|
||||
Configuration.Instance.DecryptKey = converter.decryptKey;
|
||||
|
||||
@@ -117,46 +114,58 @@ namespace FileLiberator
|
||||
}
|
||||
|
||||
private static void moveFilesToBooksDir(Book product, string outputAudioFilename)
|
||||
{
|
||||
// files are: temp path\author\[asin].ext
|
||||
var m4bDir = new FileInfo(outputAudioFilename).Directory;
|
||||
var files = m4bDir
|
||||
.EnumerateFiles()
|
||||
.Where(f => f.Name.ContainsInsensitive(product.AudibleProductId))
|
||||
.ToList();
|
||||
{
|
||||
// create final directory. move each file into it. MOVE AUDIO FILE LAST
|
||||
// new dir: safetitle_limit50char + " [" + productId + "]"
|
||||
|
||||
// create final directory. move each file into it. MOVE AUDIO FILE LAST
|
||||
// new dir: safetitle_limit50char + " [" + productId + "]"
|
||||
var destinationDir = getDestDir(product);
|
||||
Directory.CreateDirectory(destinationDir);
|
||||
|
||||
// to prevent the paths from getting too long, we don't need after the 1st ":" for the folder
|
||||
var underscoreIndex = product.Title.IndexOf(':');
|
||||
var titleDir = (underscoreIndex < 4) ? product.Title : product.Title.Substring(0, underscoreIndex);
|
||||
var finalDir = FileUtility.GetValidFilename(AudibleFileStorage.BooksDirectory, titleDir, null, product.AudibleProductId);
|
||||
Directory.CreateDirectory(finalDir);
|
||||
var sortedFiles = getProductFilesSorted(product, outputAudioFilename);
|
||||
|
||||
// move audio files to the end of the collection so these files are moved last
|
||||
var musicFiles = files.Where(f => AudibleFileStorage.Audio.IsFileTypeMatch(f));
|
||||
files = files
|
||||
.Except(musicFiles)
|
||||
.Concat(musicFiles)
|
||||
.ToList();
|
||||
var musicFileExt = Path.GetExtension(outputAudioFilename).Trim('.');
|
||||
|
||||
var musicFileExt = musicFiles
|
||||
.Select(f => f.Extension)
|
||||
.Distinct()
|
||||
.Single()
|
||||
.Trim('.');
|
||||
foreach (var f in sortedFiles)
|
||||
{
|
||||
var dest = AudibleFileStorage.Audio.IsFileTypeMatch(f)
|
||||
// audio filename: safetitle_limit50char + " [" + productId + "]." + audio_ext
|
||||
? FileUtility.GetValidFilename(destinationDir, product.Title, musicFileExt, product.AudibleProductId)
|
||||
// non-audio filename: safetitle_limit50char + " [" + productId + "][" + audio_ext +"]." + non_audio_ext
|
||||
: FileUtility.GetValidFilename(destinationDir, product.Title, f.Extension, product.AudibleProductId, musicFileExt);
|
||||
|
||||
foreach (var f in files)
|
||||
{
|
||||
var dest = AudibleFileStorage.Audio.IsFileTypeMatch(f)
|
||||
// audio filename: safetitle_limit50char + " [" + productId + "]." + audio_ext
|
||||
? FileUtility.GetValidFilename(finalDir, product.Title, musicFileExt, product.AudibleProductId)
|
||||
// non-audio filename: safetitle_limit50char + " [" + productId + "][" + audio_ext +"]." + non_audio_ext
|
||||
: FileUtility.GetValidFilename(finalDir, product.Title, f.Extension, product.AudibleProductId, musicFileExt);
|
||||
File.Move(f.FullName, dest);
|
||||
}
|
||||
}
|
||||
|
||||
File.Move(f.FullName, dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
private static string getDestDir(Book product)
|
||||
{
|
||||
// to prevent the paths from getting too long, we don't need after the 1st ":" for the folder
|
||||
var underscoreIndex = product.Title.IndexOf(':');
|
||||
var titleDir
|
||||
= underscoreIndex < 4
|
||||
? product.Title
|
||||
: product.Title.Substring(0, underscoreIndex);
|
||||
var finalDir = FileUtility.GetValidFilename(AudibleFileStorage.BooksDirectory, titleDir, null, product.AudibleProductId);
|
||||
return finalDir;
|
||||
}
|
||||
|
||||
private static List<FileInfo> getProductFilesSorted(Book product, string outputAudioFilename)
|
||||
{
|
||||
// files are: temp path\author\[asin].ext
|
||||
var m4bDir = new FileInfo(outputAudioFilename).Directory;
|
||||
var files = m4bDir
|
||||
.EnumerateFiles()
|
||||
.Where(f => f.Name.ContainsInsensitive(product.AudibleProductId))
|
||||
.ToList();
|
||||
|
||||
// move audio files to the end of the collection so these files are moved last
|
||||
var musicFiles = files.Where(f => AudibleFileStorage.Audio.IsFileTypeMatch(f));
|
||||
var sortedFiles = files
|
||||
.Except(musicFiles)
|
||||
.Concat(musicFiles)
|
||||
.ToList();
|
||||
|
||||
return sortedFiles;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,14 @@ namespace FileLiberator
|
||||
tempAaxFilename,
|
||||
(p) => api.DownloadAaxWorkaroundAsync(libraryBook.Book.AudibleProductId, tempAaxFilename, p));
|
||||
|
||||
// if bad file download, a 0-33 byte file will be created
|
||||
System.Threading.Thread.Sleep(100);
|
||||
if (new FileInfo(actualFilePath).Length < 100)
|
||||
{
|
||||
File.Delete(actualFilePath);
|
||||
throw new Exception("Error downloading file");
|
||||
}
|
||||
|
||||
return actualFilePath;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ namespace FileLiberator
|
||||
{
|
||||
public abstract class DownloadableBase : IDownloadable
|
||||
{
|
||||
public event EventHandler<string> Begin;
|
||||
public event EventHandler<string> Completed;
|
||||
public event EventHandler<LibraryBook> Begin;
|
||||
public event EventHandler<LibraryBook> Completed;
|
||||
|
||||
public event EventHandler<string> DownloadBegin;
|
||||
public event EventHandler<DownloadProgress> DownloadProgressChanged;
|
||||
@@ -26,9 +26,7 @@ namespace FileLiberator
|
||||
// often calls events which prints to forms in the UI context
|
||||
public async Task<StatusHandler> ProcessAsync(LibraryBook libraryBook)
|
||||
{
|
||||
var displayMessage = $"[{libraryBook.Book.AudibleProductId}] {libraryBook.Book.Title}";
|
||||
|
||||
Begin?.Invoke(this, displayMessage);
|
||||
Begin?.Invoke(this, libraryBook);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -36,7 +34,7 @@ namespace FileLiberator
|
||||
}
|
||||
finally
|
||||
{
|
||||
Completed?.Invoke(this, displayMessage);
|
||||
Completed?.Invoke(this, libraryBook);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
using System;
|
||||
using Dinah.Core.Net.Http;
|
||||
|
||||
namespace FileLiberator
|
||||
{
|
||||
public interface IDownloadable : IProcessable
|
||||
{
|
||||
event EventHandler<string> DownloadBegin;
|
||||
event EventHandler<Dinah.Core.Net.Http.DownloadProgress> DownloadProgressChanged;
|
||||
event EventHandler<DownloadProgress> DownloadProgressChanged;
|
||||
event EventHandler<string> DownloadCompleted;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,12 +7,12 @@ namespace FileLiberator
|
||||
{
|
||||
public interface IProcessable
|
||||
{
|
||||
event EventHandler<string> Begin;
|
||||
event EventHandler<LibraryBook> Begin;
|
||||
|
||||
/// <summary>General string message to display. DON'T rely on this for success, failure, or control logic</summary>
|
||||
event EventHandler<string> StatusUpdate;
|
||||
|
||||
event EventHandler<string> Completed;
|
||||
event EventHandler<LibraryBook> Completed;
|
||||
|
||||
/// <returns>True == Valid</returns>
|
||||
bool Validate(LibraryBook libraryBook);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using ApplicationServices;
|
||||
using DataLayer;
|
||||
using Dinah.Core.ErrorHandling;
|
||||
|
||||
@@ -17,28 +19,51 @@ namespace FileLiberator
|
||||
/// <returns>Returns either the status handler from the process, or null if all books have been processed</returns>
|
||||
public static async Task<StatusHandler> ProcessFirstValidAsync(this IProcessable processable)
|
||||
{
|
||||
var libraryBook = processable.GetNextValid();
|
||||
var libraryBook = processable.getNextValidBook();
|
||||
if (libraryBook == null)
|
||||
return null;
|
||||
|
||||
// this should never happen. check anyway. ProcessFirstValidAsync returning null is the signal that we're done. we can't let another IProcessable accidentally send this commans
|
||||
var status = await processable.ProcessAsync(libraryBook);
|
||||
return await processBookAsync(processable, libraryBook);
|
||||
}
|
||||
|
||||
/// <summary>Process the first valid product. Create default context</summary>
|
||||
/// <returns>Returns either the status handler from the process, or null if all books have been processed</returns>
|
||||
public static async Task<StatusHandler> ProcessSingleAsync(this IProcessable processable, string productId)
|
||||
{
|
||||
using var context = DbContexts.GetContext();
|
||||
var libraryBook = context
|
||||
.Library
|
||||
.GetLibrary()
|
||||
.SingleOrDefault(lb => lb.Book.AudibleProductId == productId);
|
||||
|
||||
if (libraryBook == null)
|
||||
return null;
|
||||
if (!processable.Validate(libraryBook))
|
||||
return new StatusHandler { "Validation failed" };
|
||||
|
||||
return await processBookAsync(processable, libraryBook);
|
||||
}
|
||||
|
||||
private static async Task<StatusHandler> processBookAsync(IProcessable processable, LibraryBook libraryBook)
|
||||
{
|
||||
// this should never happen. check anyway. ProcessFirstValidAsync returning null is the signal that we're done. we can't let another IProcessable accidentally send this command
|
||||
var status = await processable.ProcessAsync(libraryBook);
|
||||
if (status == null)
|
||||
throw new Exception("Processable should never return a null status");
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
public static LibraryBook GetNextValid(this IProcessable processable)
|
||||
private static LibraryBook getNextValidBook(this IProcessable processable)
|
||||
{
|
||||
var libraryBooks = LibraryQueries.GetLibrary_Flat_NoTracking();
|
||||
var libraryBooks = DbContexts.GetContext().GetLibrary_Flat_NoTracking();
|
||||
|
||||
foreach (var libraryBook in libraryBooks)
|
||||
if (processable.Validate(libraryBook))
|
||||
return libraryBook;
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<StatusHandler> TryProcessAsync(this IProcessable processable, LibraryBook libraryBook)
|
||||
=> processable.Validate(libraryBook)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Polly" Version="7.1.1" />
|
||||
<PackageReference Include="Polly" Version="7.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace FileManager
|
||||
Configuration.Instance.DecryptInProgressEnum = "WinTemp";
|
||||
var M4bRootDir
|
||||
= Configuration.Instance.DecryptInProgressEnum == "WinTemp" // else "LibationFiles"
|
||||
? Configuration.Instance.WinTemp
|
||||
? Configuration.WinTemp
|
||||
: Configuration.Instance.LibationFiles;
|
||||
DecryptInProgress = Path.Combine(M4bRootDir, "DecryptInProgress");
|
||||
Directory.CreateDirectory(DecryptInProgress);
|
||||
@@ -50,7 +50,7 @@ namespace FileManager
|
||||
Configuration.Instance.DownloadsInProgressEnum = "WinTemp";
|
||||
var AaxRootDir
|
||||
= Configuration.Instance.DownloadsInProgressEnum == "WinTemp" // else "LibationFiles"
|
||||
? Configuration.Instance.WinTemp
|
||||
? Configuration.WinTemp
|
||||
: Configuration.Instance.LibationFiles;
|
||||
DownloadsInProgress = Path.Combine(AaxRootDir, "DownloadsInProgress");
|
||||
Directory.CreateDirectory(DownloadsInProgress);
|
||||
|
||||
@@ -4,6 +4,8 @@ using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Dinah.Core;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace FileManager
|
||||
{
|
||||
@@ -31,162 +33,164 @@ namespace FileManager
|
||||
*/
|
||||
#endregion
|
||||
|
||||
private const string configFilename = "LibationSettings.json";
|
||||
private PersistentDictionary persistentDictionary;
|
||||
|
||||
private PersistentDictionary persistentDictionary { get; }
|
||||
public bool FilesExist
|
||||
=> File.Exists(APPSETTINGS_JSON)
|
||||
&& File.Exists(SettingsJsonPath)
|
||||
&& Directory.Exists(LibationFiles)
|
||||
&& Directory.Exists(Books);
|
||||
|
||||
[Description("Location of the configuration file where these settings are saved. Please do not edit this file directly while Libation is running.")]
|
||||
public string Filepath { get; }
|
||||
public string SettingsJsonPath => Path.Combine(LibationFiles, "Settings.json");
|
||||
|
||||
[Description("[Advanced. Leave alone in most cases.] Your user-specific key used to decrypt your audible files (*.aax) into audio files you can use anywhere (*.m4b)")]
|
||||
[Description("Your user-specific key used to decrypt your audible files (*.aax) into audio files you can use anywhere (*.m4b). Leave alone in most cases")]
|
||||
public string DecryptKey
|
||||
{
|
||||
get => persistentDictionary[nameof(DecryptKey)];
|
||||
set => persistentDictionary[nameof(DecryptKey)] = value;
|
||||
get => persistentDictionary.GetString(nameof(DecryptKey));
|
||||
set => persistentDictionary.Set(nameof(DecryptKey), value);
|
||||
}
|
||||
|
||||
[Description("Location for book storage. Includes destination of newly liberated books")]
|
||||
public string Books
|
||||
{
|
||||
get => persistentDictionary[nameof(Books)];
|
||||
set => persistentDictionary[nameof(Books)] = value;
|
||||
get => persistentDictionary.GetString(nameof(Books));
|
||||
set => persistentDictionary.Set(nameof(Books), value);
|
||||
}
|
||||
|
||||
public string WinTemp { get; } = Path.Combine(Path.GetTempPath(), "Libation");
|
||||
private const string APP_DIR = "AppDir";
|
||||
public static string AppDir { get; } = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(Exe.FileLocationOnDisk), LIBATION_FILES));
|
||||
public static string MyDocs { get; } = Path.GetFullPath(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), LIBATION_FILES));
|
||||
public static string WinTemp { get; } = Path.GetFullPath(Path.Combine(Path.GetTempPath(), "Libation"));
|
||||
|
||||
[Description("Location for storage of program-created files")]
|
||||
public string LibationFiles
|
||||
private Dictionary<string, string> wellKnownPaths { get; } = new Dictionary<string, string>
|
||||
{
|
||||
get => persistentDictionary[nameof(LibationFiles)];
|
||||
set => persistentDictionary[nameof(LibationFiles)] = value;
|
||||
}
|
||||
[APP_DIR] = AppDir,
|
||||
["MyDocs"] = MyDocs,
|
||||
["WinTemp"] = WinTemp
|
||||
};
|
||||
private string libationFilesPathCache;
|
||||
|
||||
// default setting and directory creation occur in class responsible for files.
|
||||
// config class is only responsible for path. not responsible for setting defaults, dir validation, or dir creation
|
||||
// exceptions: appsettings.json, LibationFiles dir, Settings.json
|
||||
|
||||
// temp/working dir(s) should be outside of dropbox
|
||||
[Description("Temporary location of files while they're in process of being downloaded.\r\nWhen download is complete, the final file will be in [LibationFiles]\\DownloadsFinal")]
|
||||
public string DownloadsInProgressEnum
|
||||
{
|
||||
get => persistentDictionary[nameof(DownloadsInProgressEnum)];
|
||||
set => persistentDictionary[nameof(DownloadsInProgressEnum)] = value;
|
||||
get => persistentDictionary.GetString(nameof(DownloadsInProgressEnum));
|
||||
set => persistentDictionary.Set(nameof(DownloadsInProgressEnum), value);
|
||||
}
|
||||
|
||||
// temp/working dir(s) should be outside of dropbox
|
||||
[Description("Temporary location of files while they're in process of being decrypted.\r\nWhen decryption is complete, the final file will be in Books location")]
|
||||
public string DecryptInProgressEnum
|
||||
{
|
||||
get => persistentDictionary[nameof(DecryptInProgressEnum)];
|
||||
set => persistentDictionary[nameof(DecryptInProgressEnum)] = value;
|
||||
get => persistentDictionary.GetString(nameof(DecryptInProgressEnum));
|
||||
set => persistentDictionary.Set(nameof(DecryptInProgressEnum), value);
|
||||
}
|
||||
|
||||
public string LocaleCountryCode
|
||||
{
|
||||
get => persistentDictionary[nameof(LocaleCountryCode)];
|
||||
set => persistentDictionary[nameof(LocaleCountryCode)] = value;
|
||||
}
|
||||
public string LocaleCountryCode
|
||||
{
|
||||
get => persistentDictionary.GetString(nameof(LocaleCountryCode));
|
||||
set => persistentDictionary.Set(nameof(LocaleCountryCode), value);
|
||||
}
|
||||
|
||||
// note: any potential file manager static ctors can't compensate if storage dir is changed at run time via settings. this is partly bad architecture. but the side effect is desirable. if changing LibationFiles location: restart app
|
||||
|
||||
// singleton stuff
|
||||
public static Configuration Instance { get; } = new Configuration();
|
||||
private Configuration()
|
||||
private Configuration() { }
|
||||
|
||||
private const string APPSETTINGS_JSON = "appsettings.json";
|
||||
private const string LIBATION_FILES = "LibationFiles";
|
||||
|
||||
[Description("Location for storage of program-created files")]
|
||||
public string LibationFiles => libationFilesPathCache ?? getLibationFiles();
|
||||
private string getLibationFiles()
|
||||
{
|
||||
Filepath = getPath();
|
||||
var value = getLiberationFilesSettingFromJson();
|
||||
|
||||
// load json values into memory
|
||||
persistentDictionary = new PersistentDictionary(Filepath);
|
||||
ensureDictionaryEntries();
|
||||
// this looks weird but is correct for translating wellKnownPaths
|
||||
if (wellKnownPaths.ContainsKey(value))
|
||||
value = wellKnownPaths[value];
|
||||
|
||||
// setUserFilesDirectoryDefault
|
||||
// don't create dir. dir creation is the responsibility of places that use the dir
|
||||
if (string.IsNullOrWhiteSpace(LibationFiles))
|
||||
LibationFiles = Path.Combine(Path.GetDirectoryName(Exe.FileLocationOnDisk), "Libation");
|
||||
// must write here before SettingsJsonPath in next step reads cache
|
||||
libationFilesPathCache = value;
|
||||
|
||||
// load json values into memory. create if not exists
|
||||
persistentDictionary = new PersistentDictionary(SettingsJsonPath);
|
||||
|
||||
return libationFilesPathCache;
|
||||
}
|
||||
private string getLiberationFilesSettingFromJson()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (File.Exists(APPSETTINGS_JSON))
|
||||
{
|
||||
var appSettingsContents = File.ReadAllText(APPSETTINGS_JSON);
|
||||
var jObj = JObject.Parse(appSettingsContents);
|
||||
|
||||
if (jObj.ContainsKey(LIBATION_FILES))
|
||||
{
|
||||
var value = jObj[LIBATION_FILES].Value<string>();
|
||||
|
||||
// do not check whether directory exists. special/meta directory (eg: AppDir) is valid
|
||||
if (!string.IsNullOrWhiteSpace(value))
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
File.WriteAllText(APPSETTINGS_JSON, new JObject { { LIBATION_FILES, APP_DIR } }.ToString(Formatting.Indented));
|
||||
return APP_DIR;
|
||||
}
|
||||
|
||||
public object GetObject(string propertyName) => persistentDictionary.GetObject(propertyName);
|
||||
public void SetObject(string propertyName, object newValue) => persistentDictionary.Set(propertyName, newValue);
|
||||
public void SetWithJsonPath(string jsonPath, string propertyName, string newValue) => persistentDictionary.SetWithJsonPath(jsonPath, propertyName, newValue);
|
||||
|
||||
public static string GetDescription(string propertyName)
|
||||
{
|
||||
var attribute = typeof(Configuration)
|
||||
.GetProperty(propertyName)
|
||||
?.GetCustomAttributes(typeof(DescriptionAttribute), true)
|
||||
.SingleOrDefault()
|
||||
as DescriptionAttribute;
|
||||
var attribute = typeof(Configuration)
|
||||
.GetProperty(propertyName)
|
||||
?.GetCustomAttributes(typeof(DescriptionAttribute), true)
|
||||
.SingleOrDefault()
|
||||
as DescriptionAttribute;
|
||||
|
||||
return attribute?.Description;
|
||||
}
|
||||
return attribute?.Description;
|
||||
}
|
||||
|
||||
private static string getPath()
|
||||
public bool TrySetLibationFiles(string directory)
|
||||
{
|
||||
// search folders for config file. accept the first match
|
||||
var defaultdir = Path.GetDirectoryName(Exe.FileLocationOnDisk);
|
||||
if (!Directory.Exists(directory) && !wellKnownPaths.ContainsKey(directory))
|
||||
return false;
|
||||
|
||||
var baseDirs = new HashSet<string>
|
||||
// if moving from default, delete old settings file and dir (if empty)
|
||||
if (LibationFiles.EqualsInsensitive(AppDir))
|
||||
{
|
||||
defaultdir,
|
||||
getNonDevelopmentDir(defaultdir),
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.Personal)
|
||||
};
|
||||
|
||||
var subDirs = baseDirs.Select(dir => Path.Combine(dir, "Libation"));
|
||||
var dirs = baseDirs.Concat(subDirs).ToList();
|
||||
|
||||
foreach (var dir in dirs)
|
||||
{
|
||||
var f = Path.Combine(dir, configFilename);
|
||||
if (File.Exists(f))
|
||||
return f;
|
||||
File.Delete(SettingsJsonPath);
|
||||
System.Threading.Thread.Sleep(100);
|
||||
if (!Directory.EnumerateDirectories(AppDir).Any() && !Directory.EnumerateFiles(AppDir).Any())
|
||||
Directory.Delete(AppDir);
|
||||
}
|
||||
|
||||
return Path.Combine(defaultdir, configFilename);
|
||||
}
|
||||
|
||||
private static string getNonDevelopmentDir(string path)
|
||||
{
|
||||
// examples:
|
||||
// \Libation\Core2_0\bin\Debug\netcoreapp3.0
|
||||
// \Libation\StndLib\bin\Debug\netstandard2.1
|
||||
// \Libation\MyWnfrm\bin\Debug
|
||||
// \Libation\Core2_0\bin\Release\netcoreapp3.0
|
||||
// \Libation\StndLib\bin\Release\netstandard2.1
|
||||
// \Libation\MyWnfrm\bin\Release
|
||||
libationFilesPathCache = null;
|
||||
|
||||
var curr = new DirectoryInfo(path);
|
||||
|
||||
if (!curr.Name.EqualsInsensitive("debug") && !curr.Name.EqualsInsensitive("release") && !curr.Name.StartsWithInsensitive("netcoreapp") && !curr.Name.StartsWithInsensitive("netstandard"))
|
||||
return path;
|
||||
var contents = File.ReadAllText(APPSETTINGS_JSON);
|
||||
var jObj = JObject.Parse(contents);
|
||||
|
||||
// get out of netcore/standard dir => debug
|
||||
if (curr.Name.StartsWithInsensitive("netcoreapp") || curr.Name.StartsWithInsensitive("netstandard"))
|
||||
curr = curr.Parent;
|
||||
jObj[LIBATION_FILES] = directory;
|
||||
|
||||
if (!curr.Name.EqualsInsensitive("debug") && !curr.Name.EqualsInsensitive("release"))
|
||||
return path;
|
||||
var output = JsonConvert.SerializeObject(jObj, Formatting.Indented);
|
||||
File.WriteAllText(APPSETTINGS_JSON, output);
|
||||
|
||||
// get out of debug => bin
|
||||
curr = curr.Parent;
|
||||
if (!curr.Name.EqualsInsensitive("bin"))
|
||||
return path;
|
||||
|
||||
// get out of bin
|
||||
curr = curr.Parent;
|
||||
// get out of csproj-level dir
|
||||
curr = curr.Parent;
|
||||
|
||||
// curr should now be sln-level dir
|
||||
return curr.FullName;
|
||||
}
|
||||
|
||||
private void ensureDictionaryEntries()
|
||||
{
|
||||
var stringProperties = getDictionaryProperties().Select(p => p.Name).ToList();
|
||||
var missingKeys = stringProperties.Except(persistentDictionary.Keys).ToArray();
|
||||
persistentDictionary.AddKeys(missingKeys);
|
||||
}
|
||||
|
||||
private IEnumerable<System.Reflection.PropertyInfo> dicPropertiesCache;
|
||||
private IEnumerable<System.Reflection.PropertyInfo> getDictionaryProperties()
|
||||
{
|
||||
if (dicPropertiesCache == null)
|
||||
dicPropertiesCache = PersistentDictionary.GetPropertiesToPersist(this.GetType());
|
||||
return dicPropertiesCache;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Dinah.Core.Collections.Immutable;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace FileManager
|
||||
{
|
||||
public static class FilePathCache
|
||||
public static class FilePathCache
|
||||
{
|
||||
internal class CacheEntry
|
||||
{
|
||||
@@ -15,27 +16,30 @@ namespace FileManager
|
||||
public string Path { get; set; }
|
||||
}
|
||||
|
||||
static List<CacheEntry> inMemoryCache { get; } = new List<CacheEntry>();
|
||||
static Cache<CacheEntry> cache { get; } = new Cache<CacheEntry>();
|
||||
|
||||
public static string JsonFile => Path.Combine(Configuration.Instance.LibationFiles, "FilePaths.json");
|
||||
|
||||
static FilePathCache()
|
||||
{
|
||||
// load json into memory. if file doesn't exist, nothing to do. save() will create if needed
|
||||
if (FileUtility.FileExists(JsonFile))
|
||||
inMemoryCache = JsonConvert.DeserializeObject<List<CacheEntry>>(File.ReadAllText(JsonFile));
|
||||
// load json into memory. if file doesn't exist, nothing to do. save() will create if needed
|
||||
if (File.Exists(JsonFile))
|
||||
{
|
||||
var list = JsonConvert.DeserializeObject<List<CacheEntry>>(File.ReadAllText(JsonFile));
|
||||
cache = new Cache<CacheEntry>(list);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool Exists(string id, FileType type) => GetPath(id, type) != null;
|
||||
|
||||
public static string GetPath(string id, FileType type)
|
||||
{
|
||||
var entry = inMemoryCache.SingleOrDefault(i => i.Id == id && i.FileType == type);
|
||||
var entry = cache.SingleOrDefault(i => i.Id == id && i.FileType == type);
|
||||
|
||||
if (entry == null)
|
||||
return null;
|
||||
|
||||
if (!FileUtility.FileExists(entry.Path))
|
||||
if (!File.Exists(entry.Path))
|
||||
{
|
||||
remove(entry);
|
||||
return null;
|
||||
@@ -44,51 +48,47 @@ namespace FileManager
|
||||
return entry.Path;
|
||||
}
|
||||
|
||||
private static object locker { get; } = new object();
|
||||
|
||||
private static void remove(CacheEntry entry)
|
||||
{
|
||||
lock (locker)
|
||||
{
|
||||
inMemoryCache.Remove(entry);
|
||||
save();
|
||||
}
|
||||
}
|
||||
{
|
||||
cache.Remove(entry);
|
||||
save();
|
||||
}
|
||||
|
||||
public static void Upsert(string id, FileType type, string path)
|
||||
{
|
||||
if (!FileUtility.FileExists(path))
|
||||
if (!File.Exists(path))
|
||||
throw new FileNotFoundException("Cannot add path to cache. File not found");
|
||||
|
||||
lock (locker)
|
||||
{
|
||||
var entry = inMemoryCache.SingleOrDefault(i => i.Id == id && i.FileType == type);
|
||||
if (entry != null)
|
||||
entry.Path = path;
|
||||
else
|
||||
{
|
||||
entry = new CacheEntry { Id = id, FileType = type, Path = path };
|
||||
inMemoryCache.Add(entry);
|
||||
}
|
||||
save();
|
||||
}
|
||||
}
|
||||
var entry = cache.SingleOrDefault(i => i.Id == id && i.FileType == type);
|
||||
|
||||
// ONLY call this within lock()
|
||||
private static void save()
|
||||
{
|
||||
// create json if not exists
|
||||
void resave() => File.WriteAllText(JsonFile, JsonConvert.SerializeObject(inMemoryCache, Formatting.Indented));
|
||||
try { resave(); }
|
||||
catch (IOException)
|
||||
{
|
||||
try { resave(); }
|
||||
catch (IOException)
|
||||
{
|
||||
Console.WriteLine("...that's not good");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
if (entry is null)
|
||||
cache.Add(new CacheEntry { Id = id, FileType = type, Path = path });
|
||||
else
|
||||
entry.Path = path;
|
||||
|
||||
save();
|
||||
}
|
||||
|
||||
// cache is thread-safe and lock free. but file saving is not
|
||||
private static object locker { get; } = new object();
|
||||
private static void save()
|
||||
{
|
||||
// create json if not exists
|
||||
static void resave() => File.WriteAllText(JsonFile, JsonConvert.SerializeObject(cache.ToList(), Formatting.Indented));
|
||||
|
||||
lock (locker)
|
||||
{
|
||||
try { resave(); }
|
||||
catch (IOException)
|
||||
{
|
||||
try { resave(); }
|
||||
catch (IOException ex)
|
||||
{
|
||||
Serilog.Log.Logger.Error(ex, "Error saving FilePaths.json");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace FileManager
|
||||
{
|
||||
public static class FileUtility
|
||||
{
|
||||
// a replacement for File.Exists() which allows long paths
|
||||
// not needed in .net-core
|
||||
public static bool FileExists(string path)
|
||||
{
|
||||
var basic = File.Exists(path);
|
||||
if (basic)
|
||||
return true;
|
||||
|
||||
// character cutoff is usually 269 but this isn't a hard number. there are edgecases which shorted the threshold
|
||||
if (path.Length < 260)
|
||||
return false;
|
||||
|
||||
// try long name prefix:
|
||||
// \\?\
|
||||
// https://blogs.msdn.microsoft.com/jeremykuhne/2016/06/21/more-on-new-net-path-handling/
|
||||
path = @"\\?\" + path;
|
||||
|
||||
return File.Exists(path);
|
||||
}
|
||||
|
||||
public static string GetValidFilename(string dirFullPath, string filename, string extension, params string[] metadataSuffixes)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(dirFullPath))
|
||||
@@ -51,7 +29,7 @@ namespace FileManager
|
||||
// ensure uniqueness
|
||||
var fullfilename = Path.Combine(dirFullPath, filename + extension);
|
||||
var i = 0;
|
||||
while (FileExists(fullfilename))
|
||||
while (File.Exists(fullfilename))
|
||||
fullfilename = Path.Combine(dirFullPath, filename + $" ({++i})" + extension);
|
||||
|
||||
return fullfilename;
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace FileManager
|
||||
{
|
||||
@@ -10,70 +11,99 @@ namespace FileManager
|
||||
{
|
||||
public string Filepath { get; }
|
||||
|
||||
// forgiving -- doesn't drop settings. old entries will continue to be persisted even if not publicly visible
|
||||
private Dictionary<string, string> settingsDic { get; }
|
||||
|
||||
public string this[string key]
|
||||
{
|
||||
get => settingsDic[key];
|
||||
set
|
||||
{
|
||||
if (settingsDic.ContainsKey(key) && settingsDic[key] == value)
|
||||
return;
|
||||
|
||||
settingsDic[key] = value;
|
||||
|
||||
// auto-save to file
|
||||
save();
|
||||
}
|
||||
}
|
||||
// optimize for strings. expectation is most settings will be strings and a rare exception will be something else
|
||||
private Dictionary<string, string> stringCache { get; } = new Dictionary<string, string>();
|
||||
private Dictionary<string, object> objectCache { get; } = new Dictionary<string, object>();
|
||||
|
||||
public PersistentDictionary(string filepath)
|
||||
{
|
||||
Filepath = filepath;
|
||||
|
||||
// not found. create blank file
|
||||
if (!File.Exists(Filepath))
|
||||
{
|
||||
File.WriteAllText(Filepath, "{}");
|
||||
|
||||
// give system time to create file before first use
|
||||
System.Threading.Thread.Sleep(100);
|
||||
}
|
||||
|
||||
settingsDic = JsonConvert.DeserializeObject<Dictionary<string, string>>(File.ReadAllText(Filepath));
|
||||
}
|
||||
|
||||
public IEnumerable<string> Keys => settingsDic.Keys.Cast<string>();
|
||||
|
||||
public void AddKeys(params string[] keys)
|
||||
{
|
||||
if (keys == null || keys.Length == 0)
|
||||
if (File.Exists(Filepath))
|
||||
return;
|
||||
|
||||
foreach (var key in keys)
|
||||
settingsDic.Add(key, null);
|
||||
save();
|
||||
// will create any missing directories, incl subdirectories. if all already exist: no action
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(filepath));
|
||||
|
||||
File.WriteAllText(Filepath, "{}");
|
||||
System.Threading.Thread.Sleep(100);
|
||||
}
|
||||
|
||||
public string GetString(string propertyName)
|
||||
{
|
||||
if (!stringCache.ContainsKey(propertyName))
|
||||
{
|
||||
var jObject = readFile();
|
||||
stringCache[propertyName] = jObject.ContainsKey(propertyName) ? jObject[propertyName].Value<string>() : null;
|
||||
}
|
||||
|
||||
return stringCache[propertyName];
|
||||
}
|
||||
|
||||
public T Get<T>(string propertyName) where T : class
|
||||
=> GetObject(propertyName) is T obj ? obj : default;
|
||||
|
||||
public object GetObject(string propertyName)
|
||||
{
|
||||
if (!objectCache.ContainsKey(propertyName))
|
||||
{
|
||||
var jObject = readFile();
|
||||
objectCache[propertyName] = jObject.ContainsKey(propertyName) ? jObject[propertyName].Value<object>() : null;
|
||||
}
|
||||
|
||||
return objectCache[propertyName];
|
||||
}
|
||||
|
||||
private object locker { get; } = new object();
|
||||
private void save()
|
||||
public void Set(string propertyName, string newValue)
|
||||
{
|
||||
// only do this check in string cache, NOT object cache
|
||||
if (stringCache[propertyName] == newValue)
|
||||
return;
|
||||
|
||||
// set cache
|
||||
stringCache[propertyName] = newValue;
|
||||
|
||||
// set in file
|
||||
lock (locker)
|
||||
File.WriteAllText(Filepath, JsonConvert.SerializeObject(settingsDic, Formatting.Indented));
|
||||
{
|
||||
var jObject = readFile();
|
||||
jObject[propertyName] = newValue;
|
||||
File.WriteAllText(Filepath, JsonConvert.SerializeObject(jObject, Formatting.Indented));
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<System.Reflection.PropertyInfo> GetPropertiesToPersist(Type type)
|
||||
=> type
|
||||
.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance)
|
||||
.Where(p =>
|
||||
// string properties only
|
||||
p.PropertyType == typeof(string)
|
||||
// exclude indexer
|
||||
&& p.GetIndexParameters().Length == 0
|
||||
// exclude read-only, write-only
|
||||
&& p.GetGetMethod(false) != null
|
||||
&& p.GetSetMethod(false) != null
|
||||
).ToList();
|
||||
public void Set(string propertyName, object newValue)
|
||||
{
|
||||
// set cache
|
||||
objectCache[propertyName] = newValue;
|
||||
|
||||
// set in file
|
||||
lock (locker)
|
||||
{
|
||||
var jObject = readFile();
|
||||
jObject[propertyName] = JToken.Parse(JsonConvert.SerializeObject(newValue));
|
||||
File.WriteAllText(Filepath, JsonConvert.SerializeObject(jObject, Formatting.Indented));
|
||||
}
|
||||
}
|
||||
|
||||
public void SetWithJsonPath(string jsonPath, string propertyName, string newValue)
|
||||
{
|
||||
lock (locker)
|
||||
{
|
||||
var jObject = readFile();
|
||||
var token = jObject.SelectToken(jsonPath);
|
||||
var debug_oldValue = (string)token[propertyName];
|
||||
token[propertyName] = newValue;
|
||||
File.WriteAllText(Filepath, JsonConvert.SerializeObject(jObject, Formatting.Indented));
|
||||
}
|
||||
}
|
||||
|
||||
private JObject readFile()
|
||||
{
|
||||
var settingsJsonContents = File.ReadAllText(Filepath);
|
||||
var jObject = JsonConvert.DeserializeObject<JObject>(settingsJsonContents);
|
||||
return jObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace FileManager
|
||||
{
|
||||
var path = getPath(def);
|
||||
cache[def]
|
||||
= FileUtility.FileExists(path)
|
||||
= File.Exists(path)
|
||||
? File.ReadAllBytes(path)
|
||||
: null;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace FileManager
|
||||
static QuickFilters()
|
||||
{
|
||||
// load json into memory. if file doesn't exist, nothing to do. save() will create if needed
|
||||
if (FileUtility.FileExists(JsonFile))
|
||||
if (File.Exists(JsonFile))
|
||||
inMemoryState = JsonConvert.DeserializeObject<FilterState>(File.ReadAllText(JsonFile));
|
||||
}
|
||||
|
||||
@@ -105,12 +105,12 @@ namespace FileManager
|
||||
catch (IOException)
|
||||
{
|
||||
try { resave(); }
|
||||
catch (IOException)
|
||||
{
|
||||
Console.WriteLine("...that's not good");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
Serilog.Log.Logger.Error(ex, "Error saving QuickFilters.json");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
11
FileManager/UNTESTED/SqliteStorage.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using System.IO;
|
||||
|
||||
namespace FileManager
|
||||
{
|
||||
public static class SqliteStorage
|
||||
{
|
||||
// not customizable. don't move to config
|
||||
private static string databasePath => Path.Combine(Configuration.Instance.LibationFiles, "LibationContext.db");
|
||||
public static string ConnectionString => $"Data Source={databasePath};Foreign Keys=False;";
|
||||
}
|
||||
}
|
||||
@@ -27,11 +27,13 @@ namespace FileManager
|
||||
= Policy.Handle<Exception>()
|
||||
.WaitAndRetry(new[] { TimeSpan.FromMilliseconds(100) });
|
||||
|
||||
public static void Save(string productId, string tags)
|
||||
public static void Save(IEnumerable<(string productId, string tags)> tagsCollection)
|
||||
{
|
||||
ensureCache();
|
||||
|
||||
cache[productId] = tags;
|
||||
// on initial reload, there's a huge benefit to adding to cache individually then updating the file only once
|
||||
foreach ((string productId, string tags) in tagsCollection)
|
||||
cache[productId] = tags;
|
||||
|
||||
lock (locker)
|
||||
policy.Execute(() => File.WriteAllText(TagsFile, JsonConvert.SerializeObject(cache, Formatting.Indented)));
|
||||
@@ -51,7 +53,7 @@ namespace FileManager
|
||||
{
|
||||
if (cache is null)
|
||||
lock (locker)
|
||||
cache = !FileUtility.FileExists(TagsFile)
|
||||
cache = !File.Exists(TagsFile)
|
||||
? new Dictionary<string, string>()
|
||||
: JsonConvert.DeserializeObject<Dictionary<string, string>>(File.ReadAllText(TagsFile));
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace InternalUtilities
|
||||
|
||||
private async Task<List<Item>> getItemsAsync(ILoginCallback callback)
|
||||
{
|
||||
var api = await getApiAsync(callback);
|
||||
var api = await EzApiCreator.GetApiAsync(AudibleApiStorage.IdentityTokensFile, callback, Configuration.Instance.LocaleCountryCode);
|
||||
var items = await AudibleApiExtensions.GetAllLibraryItemsAsync(api);
|
||||
|
||||
// remove episode parents
|
||||
@@ -62,20 +62,6 @@ namespace InternalUtilities
|
||||
return items;
|
||||
}
|
||||
|
||||
private async Task<Api> getApiAsync(ILoginCallback callback)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await EzApiCreator.GetApiAsync(AudibleApiStorage.IdentityTokensFile, callback, Configuration.Instance.LocaleCountryCode);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Serilog.Log.Logger.Error(ex, "Error getting Audible API");
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static List<IValidator> getValidators()
|
||||
{
|
||||
var type = typeof(IValidator);
|
||||
|
||||
@@ -27,11 +27,11 @@ namespace InternalUtilities
|
||||
ResponseGroups = LibraryOptions.ResponseGroupOptions.ALL_OPTIONS
|
||||
});
|
||||
|
||||
string pageStr = null;
|
||||
var pageStr = page.ToString();
|
||||
|
||||
LibraryDtoV10 libResult;
|
||||
try
|
||||
{
|
||||
pageStr = page.ToString();
|
||||
// important! use this convert method
|
||||
libResult = LibraryDtoV10.FromJson(pageStr);
|
||||
}
|
||||
@@ -43,6 +43,8 @@ namespace InternalUtilities
|
||||
|
||||
if (!libResult.Items.Any())
|
||||
break;
|
||||
else
|
||||
Serilog.Log.Logger.Information($"Page {i}: {libResult.Items.Length} results");
|
||||
|
||||
allItems.AddRange(libResult.Items);
|
||||
}
|
||||
|
||||
11
Libation.sln
@@ -50,7 +50,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AudibleApi", "..\audible ap
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AudibleApi.Tests", "..\audible api\AudibleApi\_Tests\AudibleApi.Tests\AudibleApi.Tests.csproj", "{111420E2-D4F0-4068-B46A-C4B6DCC823DC}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibationWinForm", "LibationWinForm\LibationWinForm.csproj", "{635F00E1-AAD1-45F7-BEB7-D909AD33B9F6}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibationWinForms", "LibationWinForms\LibationWinForms.csproj", "{635F00E1-AAD1-45F7-BEB7-D909AD33B9F6}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinFormsDesigner", "WinFormsDesigner\WinFormsDesigner.csproj", "{0807616A-A77A-4B08-A65A-1582B09E114B}"
|
||||
EndProject
|
||||
@@ -78,7 +78,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApplicationServices", "Appl
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dinah.Core.WindowsDesktop", "..\Dinah.Core\Dinah.Core.WindowsDesktop\Dinah.Core.WindowsDesktop.csproj", "{059CE32C-9AD6-45E9-A166-790DFFB0B730}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsDesktopUtilities", "WindowsDesktopUtilities\WindowsDesktopUtilities.csproj", "{E7EFD64D-6630-4426-B09C-B6862A92E3FD}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WindowsDesktopUtilities", "WindowsDesktopUtilities\WindowsDesktopUtilities.csproj", "{E7EFD64D-6630-4426-B09C-B6862A92E3FD}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibationLauncher", "LibationLauncher\LibationLauncher.csproj", "{F3B04A3A-20C8-4582-A54A-715AF6A5D859}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@@ -194,6 +196,10 @@ Global
|
||||
{E7EFD64D-6630-4426-B09C-B6862A92E3FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E7EFD64D-6630-4426-B09C-B6862A92E3FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E7EFD64D-6630-4426-B09C-B6862A92E3FD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F3B04A3A-20C8-4582-A54A-715AF6A5D859}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F3B04A3A-20C8-4582-A54A-715AF6A5D859}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F3B04A3A-20C8-4582-A54A-715AF6A5D859}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F3B04A3A-20C8-4582-A54A-715AF6A5D859}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -226,6 +232,7 @@ Global
|
||||
{B95650EA-25F0-449E-BA5D-99126BC5D730} = {41CDCC73-9B81-49DD-9570-C54406E852AF}
|
||||
{059CE32C-9AD6-45E9-A166-790DFFB0B730} = {43E3ACB3-E0BC-4370-8DBB-E3720C8C8FD1}
|
||||
{E7EFD64D-6630-4426-B09C-B6862A92E3FD} = {F0CBB7A7-D3FB-41FF-8F47-CF3F6A592249}
|
||||
{F3B04A3A-20C8-4582-A54A-715AF6A5D859} = {8679CAC8-9164-4007-BDD2-F004810EDA14}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {615E00ED-BAEF-4E8E-A92A-9B82D87942A9}
|
||||
|
||||
20
LibationLauncher/LibationLauncher.csproj
Normal file
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<ApplicationIcon>libation.ico</ApplicationIcon>
|
||||
<AssemblyName>Libation</AssemblyName>
|
||||
|
||||
<PublishTrimmed>true</PublishTrimmed>
|
||||
<PublishReadyToRun>true</PublishReadyToRun>
|
||||
<!-- <PublishSingleFile>true</PublishSingleFile> -->
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\LibationWinForms\LibationWinForms.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
188
LibationLauncher/Program.cs
Normal file
@@ -0,0 +1,188 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
using Dinah.Core.Logging;
|
||||
using FileManager;
|
||||
using LibationWinForms;
|
||||
using LibationWinForms.Dialogs;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Serilog;
|
||||
|
||||
namespace LibationLauncher
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
Application.SetHighDpiMode(HighDpiMode.SystemAware);
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
|
||||
createSettings();
|
||||
initLogging();
|
||||
|
||||
Application.Run(new Form1());
|
||||
}
|
||||
|
||||
private static void createSettings()
|
||||
{
|
||||
var config = Configuration.Instance;
|
||||
if (configSetupIsComplete(config))
|
||||
return;
|
||||
|
||||
var isAdvanced = false;
|
||||
|
||||
var setupDialog = new SetupDialog();
|
||||
setupDialog.NoQuestionsBtn_Click += (_, __) =>
|
||||
{
|
||||
config.DecryptKey ??= "";
|
||||
config.LocaleCountryCode ??= "us";
|
||||
config.DownloadsInProgressEnum ??= "WinTemp";
|
||||
config.DecryptInProgressEnum ??= "WinTemp";
|
||||
config.Books ??= Configuration.AppDir;
|
||||
};
|
||||
// setupDialog.BasicBtn_Click += (_, __) => // no action needed
|
||||
setupDialog.AdvancedBtn_Click += (_, __) => isAdvanced = true;
|
||||
setupDialog.ShowDialog();
|
||||
|
||||
if (isAdvanced)
|
||||
{
|
||||
var dialog = new LibationFilesDialog();
|
||||
if (dialog.ShowDialog() != DialogResult.OK)
|
||||
MessageBox.Show("Libation Files location not changed");
|
||||
}
|
||||
|
||||
if (configSetupIsComplete(config))
|
||||
return;
|
||||
|
||||
if (new SettingsDialog().ShowDialog() == DialogResult.OK)
|
||||
return;
|
||||
|
||||
MessageBox.Show("Initial set up cancelled.", "Cancelled", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
Application.Exit();
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
private static bool configSetupIsComplete(Configuration config)
|
||||
=> config.FilesExist
|
||||
&& !string.IsNullOrWhiteSpace(config.LocaleCountryCode)
|
||||
&& !string.IsNullOrWhiteSpace(config.DownloadsInProgressEnum)
|
||||
&& !string.IsNullOrWhiteSpace(config.DecryptInProgressEnum);
|
||||
|
||||
private static void initLogging()
|
||||
{
|
||||
var config = Configuration.Instance;
|
||||
|
||||
ensureLoggingConfig(config);
|
||||
ensureSerilogConfig(config);
|
||||
|
||||
// override path. always use current libation files
|
||||
var logPath = Path.Combine(Configuration.Instance.LibationFiles, "Log.log");
|
||||
config.SetWithJsonPath("Serilog.WriteTo[1].Args", "path", logPath);
|
||||
|
||||
//// hack which achieves the same
|
||||
//configuration["Serilog:WriteTo:1:Args:path"] = logPath;
|
||||
|
||||
// CONFIGURATION-DRIVEN (json)
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.AddJsonFile(config.SettingsJsonPath)
|
||||
.Build();
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
.ReadFrom.Configuration(configuration)
|
||||
.CreateLogger();
|
||||
|
||||
//// MANUAL HARD CODED
|
||||
//Log.Logger = new LoggerConfiguration()
|
||||
// .Enrich.WithCaller()
|
||||
// .MinimumLevel.Information()
|
||||
// .WriteTo.File(logPath,
|
||||
// rollingInterval: RollingInterval.Month,
|
||||
// outputTemplate: code_outputTemplate)
|
||||
// .CreateLogger();
|
||||
|
||||
Log.Logger.Information("Begin Libation");
|
||||
|
||||
// .Here() captures debug info via System.Runtime.CompilerServices attributes. Warning: expensive
|
||||
//var withLineNumbers_outputTemplate = "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message}{NewLine}in method {MemberName} at {FilePath}:{LineNumber}{NewLine}{Exception}{NewLine}";
|
||||
//Log.Logger.Here().Debug("Begin Libation. Debug with line numbers");
|
||||
}
|
||||
|
||||
private static string defaultLoggingLevel { get; } = "Information";
|
||||
private static void ensureLoggingConfig(Configuration config)
|
||||
{
|
||||
if (config.GetObject("Logging") != null)
|
||||
return;
|
||||
|
||||
// "Logging": {
|
||||
// "LogLevel": {
|
||||
// "Default": "Debug"
|
||||
// }
|
||||
// }
|
||||
var loggingObj = new JObject
|
||||
{
|
||||
{
|
||||
"LogLevel", new JObject { { "Default", defaultLoggingLevel } }
|
||||
}
|
||||
};
|
||||
config.SetObject("Logging", loggingObj);
|
||||
}
|
||||
|
||||
private static void ensureSerilogConfig(Configuration config)
|
||||
{
|
||||
if (config.GetObject("Serilog") != null)
|
||||
return;
|
||||
|
||||
// default. for reference. output example:
|
||||
// 2019-11-26 08:48:40.224 -05:00 [DBG] Begin Libation
|
||||
var default_outputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}";
|
||||
// with class and method info. output example:
|
||||
// 2019-11-26 08:48:40.224 -05:00 [DBG] (at LibationWinForms.Program.init()) Begin Libation
|
||||
var code_outputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] (at {Caller}) {Message:lj}{NewLine}{Exception}";
|
||||
|
||||
// "Serilog": {
|
||||
// "MinimumLevel": "Information"
|
||||
// "WriteTo": [
|
||||
// {
|
||||
// "Name": "Console"
|
||||
// },
|
||||
// {
|
||||
// "Name": "File",
|
||||
// "Args": {
|
||||
// "rollingInterval": "Day",
|
||||
// "outputTemplate": ...
|
||||
// }
|
||||
// }
|
||||
// ],
|
||||
// "Using": [ "Dinah.Core" ],
|
||||
// "Enrich": [ "WithCaller" ]
|
||||
// }
|
||||
var serilogObj = new JObject
|
||||
{
|
||||
{ "MinimumLevel", defaultLoggingLevel },
|
||||
{ "WriteTo", new JArray
|
||||
{
|
||||
new JObject { {"Name", "Console" } },
|
||||
new JObject
|
||||
{
|
||||
{ "Name", "File" },
|
||||
{ "Args",
|
||||
new JObject
|
||||
{
|
||||
// for this sink to work, a path must be provided. we override this below
|
||||
{ "path", Path.Combine(Configuration.Instance.LibationFiles, "_Log.log") },
|
||||
{ "rollingInterval", "Month" },
|
||||
{ "outputTemplate", code_outputTemplate }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{ "Using", new JArray{ "Dinah.Core" } }, // dll's name, NOT namespace
|
||||
{ "Enrich", new JArray{ "WithCaller" } },
|
||||
};
|
||||
config.SetObject("Serilog", serilogObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 92 KiB |
@@ -3,7 +3,6 @@ using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using DataLayer;
|
||||
using Dinah.Core;
|
||||
using FileManager;
|
||||
@@ -19,6 +18,8 @@ namespace LibationSearchEngine
|
||||
{
|
||||
public const Lucene.Net.Util.Version Version = Lucene.Net.Util.Version.LUCENE_30;
|
||||
|
||||
private LibationContext context { get; }
|
||||
|
||||
// not customizable. don't move to config
|
||||
private static string SearchEngineDirectory { get; }
|
||||
= new System.IO.DirectoryInfo(Configuration.Instance.LibationFiles).CreateSubdirectory("SearchEngine").FullName;
|
||||
@@ -160,7 +161,9 @@ namespace LibationSearchEngine
|
||||
|
||||
private Directory getIndex() => FSDirectory.Open(SearchEngineDirectory);
|
||||
|
||||
public void CreateNewIndex(bool overwrite = true)
|
||||
public SearchEngine(LibationContext context) => this.context = context;
|
||||
|
||||
public void CreateNewIndex(bool overwrite = true)
|
||||
{
|
||||
// 300 products
|
||||
// 1st run after app is started: 400ms
|
||||
@@ -172,7 +175,7 @@ namespace LibationSearchEngine
|
||||
|
||||
log();
|
||||
|
||||
var library = LibraryQueries.GetLibrary_Flat_NoTracking();
|
||||
var library = context.GetLibrary_Flat_NoTracking();
|
||||
|
||||
log();
|
||||
|
||||
@@ -233,7 +236,7 @@ namespace LibationSearchEngine
|
||||
/// <summary>Long running. Use await Task.Run(() => UpdateBook(productId))</summary>
|
||||
public void UpdateBook(string productId)
|
||||
{
|
||||
var libraryBook = LibraryQueries.GetLibraryBook_Flat_NoTracking(productId);
|
||||
var libraryBook = context.GetLibraryBook_Flat_NoTracking(productId);
|
||||
var term = new Term(_ID_, productId);
|
||||
|
||||
var document = createBookIndexDocument(libraryBook);
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using Dinah.Core.Windows.Forms;
|
||||
|
||||
namespace LibationWinForm.BookLiberation
|
||||
{
|
||||
public partial class AutomatedBackupsForm : Form
|
||||
{
|
||||
public bool KeepGoingIsChecked => keepGoingCb.Checked;
|
||||
|
||||
public AutomatedBackupsForm()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void AppendError(Exception ex) => AppendText("ERROR: " + ex.Message);
|
||||
public void AppendText(string text) => logTb.UIThread(() => logTb.AppendText($"{DateTime.Now} {text}{Environment.NewLine}"));
|
||||
|
||||
public void FinalizeUI()
|
||||
{
|
||||
keepGoingCb.Enabled = false;
|
||||
logTb.AppendText("");
|
||||
AppendText("DONE");
|
||||
}
|
||||
|
||||
private void AutomatedBackupsForm_FormClosing(object sender, FormClosingEventArgs e) => keepGoingCb.Checked = false;
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using DataLayer;
|
||||
using Dinah.Core.ErrorHandling;
|
||||
using FileLiberator;
|
||||
|
||||
namespace LibationWinForm.BookLiberation
|
||||
{
|
||||
public class BookLiberatorControllerExamples
|
||||
{
|
||||
async Task BackupBookAsync(string productId)
|
||||
{
|
||||
using var context = LibationContext.Create();
|
||||
|
||||
var libraryBook = context
|
||||
.Library
|
||||
.GetLibrary()
|
||||
.SingleOrDefault(lb => lb.Book.AudibleProductId == productId);
|
||||
|
||||
if (libraryBook == null)
|
||||
return;
|
||||
|
||||
var backupBook = new BackupBook();
|
||||
backupBook.DownloadBook.Completed += SetBackupCountsAsync;
|
||||
backupBook.DecryptBook.Completed += SetBackupCountsAsync;
|
||||
await ProcessValidateLibraryBookAsync(backupBook, libraryBook);
|
||||
}
|
||||
|
||||
static async Task<StatusHandler> ProcessValidateLibraryBookAsync(IProcessable processable, LibraryBook libraryBook)
|
||||
{
|
||||
if (!processable.Validate(libraryBook))
|
||||
return new StatusHandler { "Validation failed" };
|
||||
return await processable.ProcessAsync(libraryBook);
|
||||
}
|
||||
|
||||
// Download First Book (Download encrypted/DRM file)
|
||||
async Task DownloadFirstBookAsync()
|
||||
{
|
||||
var downloadBook = ProcessorAutomationController.GetWiredUpDownloadBook();
|
||||
downloadBook.Completed += SetBackupCountsAsync;
|
||||
await downloadBook.ProcessFirstValidAsync();
|
||||
}
|
||||
|
||||
// Decrypt First Book (Remove DRM from downloaded file)
|
||||
async Task DecryptFirstBookAsync()
|
||||
{
|
||||
var decryptBook = ProcessorAutomationController.GetWiredUpDecryptBook();
|
||||
decryptBook.Completed += SetBackupCountsAsync;
|
||||
await decryptBook.ProcessFirstValidAsync();
|
||||
}
|
||||
|
||||
// Backup First Book (Decrypt a non-liberated book. Download if needed)
|
||||
async Task BackupFirstBookAsync()
|
||||
{
|
||||
var backupBook = ProcessorAutomationController.GetWiredUpBackupBook();
|
||||
backupBook.DownloadBook.Completed += SetBackupCountsAsync;
|
||||
backupBook.DecryptBook.Completed += SetBackupCountsAsync;
|
||||
await backupBook.ProcessFirstValidAsync();
|
||||
}
|
||||
|
||||
async void SetBackupCountsAsync(object obj, string str) => throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -1,441 +0,0 @@
|
||||
namespace LibationWinForm
|
||||
{
|
||||
partial class SettingsDialog
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.settingsFileLbl = new System.Windows.Forms.Label();
|
||||
this.settingsFileTb = new System.Windows.Forms.TextBox();
|
||||
this.decryptKeyLbl = new System.Windows.Forms.Label();
|
||||
this.decryptKeyTb = new System.Windows.Forms.TextBox();
|
||||
this.booksLocationLbl = new System.Windows.Forms.Label();
|
||||
this.booksLocationTb = new System.Windows.Forms.TextBox();
|
||||
this.booksLocationSearchBtn = new System.Windows.Forms.Button();
|
||||
this.settingsFileDescLbl = new System.Windows.Forms.Label();
|
||||
this.decryptKeyDescLbl = new System.Windows.Forms.Label();
|
||||
this.booksLocationDescLbl = new System.Windows.Forms.Label();
|
||||
this.libationFilesGb = new System.Windows.Forms.GroupBox();
|
||||
this.libationFilesDescLbl = new System.Windows.Forms.Label();
|
||||
this.libationFilesCustomBtn = new System.Windows.Forms.Button();
|
||||
this.libationFilesCustomTb = new System.Windows.Forms.TextBox();
|
||||
this.libationFilesCustomRb = new System.Windows.Forms.RadioButton();
|
||||
this.libationFilesMyDocsRb = new System.Windows.Forms.RadioButton();
|
||||
this.libationFilesRootRb = new System.Windows.Forms.RadioButton();
|
||||
this.downloadsInProgressGb = new System.Windows.Forms.GroupBox();
|
||||
this.downloadsInProgressLibationFilesRb = new System.Windows.Forms.RadioButton();
|
||||
this.downloadsInProgressWinTempRb = new System.Windows.Forms.RadioButton();
|
||||
this.downloadsInProgressDescLbl = new System.Windows.Forms.Label();
|
||||
this.decryptInProgressGb = new System.Windows.Forms.GroupBox();
|
||||
this.decryptInProgressLibationFilesRb = new System.Windows.Forms.RadioButton();
|
||||
this.decryptInProgressWinTempRb = new System.Windows.Forms.RadioButton();
|
||||
this.decryptInProgressDescLbl = new System.Windows.Forms.Label();
|
||||
this.saveBtn = new System.Windows.Forms.Button();
|
||||
this.cancelBtn = new System.Windows.Forms.Button();
|
||||
this.audibleLocaleLbl = new System.Windows.Forms.Label();
|
||||
this.audibleLocaleCb = new System.Windows.Forms.ComboBox();
|
||||
this.libationFilesGb.SuspendLayout();
|
||||
this.downloadsInProgressGb.SuspendLayout();
|
||||
this.decryptInProgressGb.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// settingsFileLbl
|
||||
//
|
||||
this.settingsFileLbl.AutoSize = true;
|
||||
this.settingsFileLbl.Location = new System.Drawing.Point(7, 15);
|
||||
this.settingsFileLbl.Name = "settingsFileLbl";
|
||||
this.settingsFileLbl.Size = new System.Drawing.Size(61, 13);
|
||||
this.settingsFileLbl.TabIndex = 0;
|
||||
this.settingsFileLbl.Text = "Settings file";
|
||||
//
|
||||
// settingsFileTb
|
||||
//
|
||||
this.settingsFileTb.Location = new System.Drawing.Point(90, 12);
|
||||
this.settingsFileTb.Name = "settingsFileTb";
|
||||
this.settingsFileTb.ReadOnly = true;
|
||||
this.settingsFileTb.Size = new System.Drawing.Size(698, 20);
|
||||
this.settingsFileTb.TabIndex = 1;
|
||||
//
|
||||
// decryptKeyLbl
|
||||
//
|
||||
this.decryptKeyLbl.AutoSize = true;
|
||||
this.decryptKeyLbl.Location = new System.Drawing.Point(7, 59);
|
||||
this.decryptKeyLbl.Name = "decryptKeyLbl";
|
||||
this.decryptKeyLbl.Size = new System.Drawing.Size(64, 13);
|
||||
this.decryptKeyLbl.TabIndex = 3;
|
||||
this.decryptKeyLbl.Text = "Decrypt key";
|
||||
//
|
||||
// decryptKeyTb
|
||||
//
|
||||
this.decryptKeyTb.Location = new System.Drawing.Point(90, 56);
|
||||
this.decryptKeyTb.Name = "decryptKeyTb";
|
||||
this.decryptKeyTb.Size = new System.Drawing.Size(100, 20);
|
||||
this.decryptKeyTb.TabIndex = 4;
|
||||
//
|
||||
// booksLocationLbl
|
||||
//
|
||||
this.booksLocationLbl.AutoSize = true;
|
||||
this.booksLocationLbl.Location = new System.Drawing.Point(7, 125);
|
||||
this.booksLocationLbl.Name = "booksLocationLbl";
|
||||
this.booksLocationLbl.Size = new System.Drawing.Size(77, 13);
|
||||
this.booksLocationLbl.TabIndex = 8;
|
||||
this.booksLocationLbl.Text = "Books location";
|
||||
//
|
||||
// booksLocationTb
|
||||
//
|
||||
this.booksLocationTb.Location = new System.Drawing.Point(90, 122);
|
||||
this.booksLocationTb.Name = "booksLocationTb";
|
||||
this.booksLocationTb.Size = new System.Drawing.Size(657, 20);
|
||||
this.booksLocationTb.TabIndex = 9;
|
||||
//
|
||||
// booksLocationSearchBtn
|
||||
//
|
||||
this.booksLocationSearchBtn.Location = new System.Drawing.Point(753, 120);
|
||||
this.booksLocationSearchBtn.Name = "booksLocationSearchBtn";
|
||||
this.booksLocationSearchBtn.Size = new System.Drawing.Size(35, 23);
|
||||
this.booksLocationSearchBtn.TabIndex = 10;
|
||||
this.booksLocationSearchBtn.Text = "...";
|
||||
this.booksLocationSearchBtn.UseVisualStyleBackColor = true;
|
||||
this.booksLocationSearchBtn.Click += new System.EventHandler(this.booksLocationSearchBtn_Click);
|
||||
//
|
||||
// settingsFileDescLbl
|
||||
//
|
||||
this.settingsFileDescLbl.AutoSize = true;
|
||||
this.settingsFileDescLbl.Location = new System.Drawing.Point(87, 35);
|
||||
this.settingsFileDescLbl.Name = "settingsFileDescLbl";
|
||||
this.settingsFileDescLbl.Size = new System.Drawing.Size(36, 13);
|
||||
this.settingsFileDescLbl.TabIndex = 2;
|
||||
this.settingsFileDescLbl.Text = "[desc]";
|
||||
//
|
||||
// decryptKeyDescLbl
|
||||
//
|
||||
this.decryptKeyDescLbl.AutoSize = true;
|
||||
this.decryptKeyDescLbl.Location = new System.Drawing.Point(87, 79);
|
||||
this.decryptKeyDescLbl.Name = "decryptKeyDescLbl";
|
||||
this.decryptKeyDescLbl.Size = new System.Drawing.Size(36, 13);
|
||||
this.decryptKeyDescLbl.TabIndex = 5;
|
||||
this.decryptKeyDescLbl.Text = "[desc]";
|
||||
//
|
||||
// booksLocationDescLbl
|
||||
//
|
||||
this.booksLocationDescLbl.AutoSize = true;
|
||||
this.booksLocationDescLbl.Location = new System.Drawing.Point(87, 145);
|
||||
this.booksLocationDescLbl.Name = "booksLocationDescLbl";
|
||||
this.booksLocationDescLbl.Size = new System.Drawing.Size(36, 13);
|
||||
this.booksLocationDescLbl.TabIndex = 11;
|
||||
this.booksLocationDescLbl.Text = "[desc]";
|
||||
//
|
||||
// libationFilesGb
|
||||
//
|
||||
this.libationFilesGb.Controls.Add(this.libationFilesDescLbl);
|
||||
this.libationFilesGb.Controls.Add(this.libationFilesCustomBtn);
|
||||
this.libationFilesGb.Controls.Add(this.libationFilesCustomTb);
|
||||
this.libationFilesGb.Controls.Add(this.libationFilesCustomRb);
|
||||
this.libationFilesGb.Controls.Add(this.libationFilesMyDocsRb);
|
||||
this.libationFilesGb.Controls.Add(this.libationFilesRootRb);
|
||||
this.libationFilesGb.Location = new System.Drawing.Point(12, 161);
|
||||
this.libationFilesGb.Name = "libationFilesGb";
|
||||
this.libationFilesGb.Size = new System.Drawing.Size(776, 131);
|
||||
this.libationFilesGb.TabIndex = 12;
|
||||
this.libationFilesGb.TabStop = false;
|
||||
this.libationFilesGb.Text = "Libation files";
|
||||
//
|
||||
// libationFilesDescLbl
|
||||
//
|
||||
this.libationFilesDescLbl.AutoSize = true;
|
||||
this.libationFilesDescLbl.Location = new System.Drawing.Point(6, 16);
|
||||
this.libationFilesDescLbl.Name = "libationFilesDescLbl";
|
||||
this.libationFilesDescLbl.Size = new System.Drawing.Size(36, 13);
|
||||
this.libationFilesDescLbl.TabIndex = 0;
|
||||
this.libationFilesDescLbl.Text = "[desc]";
|
||||
//
|
||||
// libationFilesCustomBtn
|
||||
//
|
||||
this.libationFilesCustomBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.libationFilesCustomBtn.Location = new System.Drawing.Point(741, 102);
|
||||
this.libationFilesCustomBtn.Name = "libationFilesCustomBtn";
|
||||
this.libationFilesCustomBtn.Size = new System.Drawing.Size(35, 23);
|
||||
this.libationFilesCustomBtn.TabIndex = 5;
|
||||
this.libationFilesCustomBtn.Text = "...";
|
||||
this.libationFilesCustomBtn.UseVisualStyleBackColor = true;
|
||||
this.libationFilesCustomBtn.Click += new System.EventHandler(this.libationFilesCustomBtn_Click);
|
||||
//
|
||||
// libationFilesCustomTb
|
||||
//
|
||||
this.libationFilesCustomTb.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.libationFilesCustomTb.Location = new System.Drawing.Point(29, 104);
|
||||
this.libationFilesCustomTb.Name = "libationFilesCustomTb";
|
||||
this.libationFilesCustomTb.Size = new System.Drawing.Size(706, 20);
|
||||
this.libationFilesCustomTb.TabIndex = 4;
|
||||
this.libationFilesCustomTb.TextChanged += new System.EventHandler(this.libationFiles_Changed);
|
||||
//
|
||||
// libationFilesCustomRb
|
||||
//
|
||||
this.libationFilesCustomRb.AutoSize = true;
|
||||
this.libationFilesCustomRb.Location = new System.Drawing.Point(9, 107);
|
||||
this.libationFilesCustomRb.Name = "libationFilesCustomRb";
|
||||
this.libationFilesCustomRb.Size = new System.Drawing.Size(14, 13);
|
||||
this.libationFilesCustomRb.TabIndex = 3;
|
||||
this.libationFilesCustomRb.TabStop = true;
|
||||
this.libationFilesCustomRb.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// libationFilesMyDocsRb
|
||||
//
|
||||
this.libationFilesMyDocsRb.AutoSize = true;
|
||||
this.libationFilesMyDocsRb.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||
this.libationFilesMyDocsRb.Location = new System.Drawing.Point(9, 68);
|
||||
this.libationFilesMyDocsRb.Name = "libationFilesMyDocsRb";
|
||||
this.libationFilesMyDocsRb.Size = new System.Drawing.Size(111, 30);
|
||||
this.libationFilesMyDocsRb.TabIndex = 2;
|
||||
this.libationFilesMyDocsRb.TabStop = true;
|
||||
this.libationFilesMyDocsRb.Text = "[desc]\r\n[myDocs\\Libation]";
|
||||
this.libationFilesMyDocsRb.UseVisualStyleBackColor = true;
|
||||
this.libationFilesMyDocsRb.CheckedChanged += new System.EventHandler(this.libationFiles_Changed);
|
||||
//
|
||||
// libationFilesRootRb
|
||||
//
|
||||
this.libationFilesRootRb.AutoSize = true;
|
||||
this.libationFilesRootRb.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||
this.libationFilesRootRb.Location = new System.Drawing.Point(9, 32);
|
||||
this.libationFilesRootRb.Name = "libationFilesRootRb";
|
||||
this.libationFilesRootRb.Size = new System.Drawing.Size(113, 30);
|
||||
this.libationFilesRootRb.TabIndex = 1;
|
||||
this.libationFilesRootRb.TabStop = true;
|
||||
this.libationFilesRootRb.Text = "[desc]\r\n[exeRoot\\Libation]";
|
||||
this.libationFilesRootRb.UseVisualStyleBackColor = true;
|
||||
this.libationFilesRootRb.CheckedChanged += new System.EventHandler(this.libationFiles_Changed);
|
||||
//
|
||||
// downloadsInProgressGb
|
||||
//
|
||||
this.downloadsInProgressGb.Controls.Add(this.downloadsInProgressLibationFilesRb);
|
||||
this.downloadsInProgressGb.Controls.Add(this.downloadsInProgressWinTempRb);
|
||||
this.downloadsInProgressGb.Controls.Add(this.downloadsInProgressDescLbl);
|
||||
this.downloadsInProgressGb.Location = new System.Drawing.Point(12, 298);
|
||||
this.downloadsInProgressGb.Name = "downloadsInProgressGb";
|
||||
this.downloadsInProgressGb.Size = new System.Drawing.Size(776, 117);
|
||||
this.downloadsInProgressGb.TabIndex = 13;
|
||||
this.downloadsInProgressGb.TabStop = false;
|
||||
this.downloadsInProgressGb.Text = "Downloads in progress";
|
||||
//
|
||||
// downloadsInProgressLibationFilesRb
|
||||
//
|
||||
this.downloadsInProgressLibationFilesRb.AutoSize = true;
|
||||
this.downloadsInProgressLibationFilesRb.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||
this.downloadsInProgressLibationFilesRb.Location = new System.Drawing.Point(9, 81);
|
||||
this.downloadsInProgressLibationFilesRb.Name = "downloadsInProgressLibationFilesRb";
|
||||
this.downloadsInProgressLibationFilesRb.Size = new System.Drawing.Size(193, 30);
|
||||
this.downloadsInProgressLibationFilesRb.TabIndex = 2;
|
||||
this.downloadsInProgressLibationFilesRb.TabStop = true;
|
||||
this.downloadsInProgressLibationFilesRb.Text = "[desc]\r\n[libationFiles\\DownloadsInProgress]";
|
||||
this.downloadsInProgressLibationFilesRb.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// downloadsInProgressWinTempRb
|
||||
//
|
||||
this.downloadsInProgressWinTempRb.AutoSize = true;
|
||||
this.downloadsInProgressWinTempRb.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||
this.downloadsInProgressWinTempRb.Location = new System.Drawing.Point(9, 45);
|
||||
this.downloadsInProgressWinTempRb.Name = "downloadsInProgressWinTempRb";
|
||||
this.downloadsInProgressWinTempRb.Size = new System.Drawing.Size(182, 30);
|
||||
this.downloadsInProgressWinTempRb.TabIndex = 1;
|
||||
this.downloadsInProgressWinTempRb.TabStop = true;
|
||||
this.downloadsInProgressWinTempRb.Text = "[desc]\r\n[winTemp\\DownloadsInProgress]";
|
||||
this.downloadsInProgressWinTempRb.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// downloadsInProgressDescLbl
|
||||
//
|
||||
this.downloadsInProgressDescLbl.AutoSize = true;
|
||||
this.downloadsInProgressDescLbl.Location = new System.Drawing.Point(6, 16);
|
||||
this.downloadsInProgressDescLbl.Name = "downloadsInProgressDescLbl";
|
||||
this.downloadsInProgressDescLbl.Size = new System.Drawing.Size(38, 26);
|
||||
this.downloadsInProgressDescLbl.TabIndex = 0;
|
||||
this.downloadsInProgressDescLbl.Text = "[desc]\r\n[line 2]";
|
||||
//
|
||||
// decryptInProgressGb
|
||||
//
|
||||
this.decryptInProgressGb.Controls.Add(this.decryptInProgressLibationFilesRb);
|
||||
this.decryptInProgressGb.Controls.Add(this.decryptInProgressWinTempRb);
|
||||
this.decryptInProgressGb.Controls.Add(this.decryptInProgressDescLbl);
|
||||
this.decryptInProgressGb.Location = new System.Drawing.Point(12, 421);
|
||||
this.decryptInProgressGb.Name = "decryptInProgressGb";
|
||||
this.decryptInProgressGb.Size = new System.Drawing.Size(776, 117);
|
||||
this.decryptInProgressGb.TabIndex = 14;
|
||||
this.decryptInProgressGb.TabStop = false;
|
||||
this.decryptInProgressGb.Text = "Decrypt in progress";
|
||||
//
|
||||
// decryptInProgressLibationFilesRb
|
||||
//
|
||||
this.decryptInProgressLibationFilesRb.AutoSize = true;
|
||||
this.decryptInProgressLibationFilesRb.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||
this.decryptInProgressLibationFilesRb.Location = new System.Drawing.Point(6, 81);
|
||||
this.decryptInProgressLibationFilesRb.Name = "decryptInProgressLibationFilesRb";
|
||||
this.decryptInProgressLibationFilesRb.Size = new System.Drawing.Size(177, 30);
|
||||
this.decryptInProgressLibationFilesRb.TabIndex = 2;
|
||||
this.decryptInProgressLibationFilesRb.TabStop = true;
|
||||
this.decryptInProgressLibationFilesRb.Text = "[desc]\r\n[libationFiles\\DecryptInProgress]";
|
||||
this.decryptInProgressLibationFilesRb.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// decryptInProgressWinTempRb
|
||||
//
|
||||
this.decryptInProgressWinTempRb.AutoSize = true;
|
||||
this.decryptInProgressWinTempRb.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||
this.decryptInProgressWinTempRb.Location = new System.Drawing.Point(6, 45);
|
||||
this.decryptInProgressWinTempRb.Name = "decryptInProgressWinTempRb";
|
||||
this.decryptInProgressWinTempRb.Size = new System.Drawing.Size(166, 30);
|
||||
this.decryptInProgressWinTempRb.TabIndex = 1;
|
||||
this.decryptInProgressWinTempRb.TabStop = true;
|
||||
this.decryptInProgressWinTempRb.Text = "[desc]\r\n[winTemp\\DecryptInProgress]";
|
||||
this.decryptInProgressWinTempRb.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// decryptInProgressDescLbl
|
||||
//
|
||||
this.decryptInProgressDescLbl.AutoSize = true;
|
||||
this.decryptInProgressDescLbl.Location = new System.Drawing.Point(6, 16);
|
||||
this.decryptInProgressDescLbl.Name = "decryptInProgressDescLbl";
|
||||
this.decryptInProgressDescLbl.Size = new System.Drawing.Size(38, 26);
|
||||
this.decryptInProgressDescLbl.TabIndex = 0;
|
||||
this.decryptInProgressDescLbl.Text = "[desc]\r\n[line 2]";
|
||||
//
|
||||
// saveBtn
|
||||
//
|
||||
this.saveBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.saveBtn.Location = new System.Drawing.Point(612, 544);
|
||||
this.saveBtn.Name = "saveBtn";
|
||||
this.saveBtn.Size = new System.Drawing.Size(75, 23);
|
||||
this.saveBtn.TabIndex = 15;
|
||||
this.saveBtn.Text = "Save";
|
||||
this.saveBtn.UseVisualStyleBackColor = true;
|
||||
this.saveBtn.Click += new System.EventHandler(this.saveBtn_Click);
|
||||
//
|
||||
// cancelBtn
|
||||
//
|
||||
this.cancelBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.cancelBtn.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||
this.cancelBtn.Location = new System.Drawing.Point(713, 544);
|
||||
this.cancelBtn.Name = "cancelBtn";
|
||||
this.cancelBtn.Size = new System.Drawing.Size(75, 23);
|
||||
this.cancelBtn.TabIndex = 16;
|
||||
this.cancelBtn.Text = "Cancel";
|
||||
this.cancelBtn.UseVisualStyleBackColor = true;
|
||||
this.cancelBtn.Click += new System.EventHandler(this.cancelBtn_Click);
|
||||
//
|
||||
// audibleLocaleLbl
|
||||
//
|
||||
this.audibleLocaleLbl.AutoSize = true;
|
||||
this.audibleLocaleLbl.Location = new System.Drawing.Point(7, 98);
|
||||
this.audibleLocaleLbl.Name = "audibleLocaleLbl";
|
||||
this.audibleLocaleLbl.Size = new System.Drawing.Size(77, 13);
|
||||
this.audibleLocaleLbl.TabIndex = 6;
|
||||
this.audibleLocaleLbl.Text = "Audible Locale";
|
||||
//
|
||||
// audibleLocaleCb
|
||||
//
|
||||
this.audibleLocaleCb.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.audibleLocaleCb.FormattingEnabled = true;
|
||||
this.audibleLocaleCb.Items.AddRange(new object[] {
|
||||
"us",
|
||||
"uk",
|
||||
"germany",
|
||||
"france",
|
||||
"canada"});
|
||||
this.audibleLocaleCb.Location = new System.Drawing.Point(90, 95);
|
||||
this.audibleLocaleCb.Name = "audibleLocaleCb";
|
||||
this.audibleLocaleCb.Size = new System.Drawing.Size(121, 21);
|
||||
this.audibleLocaleCb.TabIndex = 7;
|
||||
//
|
||||
// SettingsDialog
|
||||
//
|
||||
this.AcceptButton = this.saveBtn;
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.CancelButton = this.cancelBtn;
|
||||
this.ClientSize = new System.Drawing.Size(800, 579);
|
||||
this.Controls.Add(this.audibleLocaleCb);
|
||||
this.Controls.Add(this.audibleLocaleLbl);
|
||||
this.Controls.Add(this.cancelBtn);
|
||||
this.Controls.Add(this.saveBtn);
|
||||
this.Controls.Add(this.decryptInProgressGb);
|
||||
this.Controls.Add(this.downloadsInProgressGb);
|
||||
this.Controls.Add(this.libationFilesGb);
|
||||
this.Controls.Add(this.booksLocationDescLbl);
|
||||
this.Controls.Add(this.decryptKeyDescLbl);
|
||||
this.Controls.Add(this.settingsFileDescLbl);
|
||||
this.Controls.Add(this.booksLocationSearchBtn);
|
||||
this.Controls.Add(this.booksLocationTb);
|
||||
this.Controls.Add(this.booksLocationLbl);
|
||||
this.Controls.Add(this.decryptKeyTb);
|
||||
this.Controls.Add(this.decryptKeyLbl);
|
||||
this.Controls.Add(this.settingsFileTb);
|
||||
this.Controls.Add(this.settingsFileLbl);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
|
||||
this.Name = "SettingsDialog";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||
this.Text = "Edit Settings";
|
||||
this.Load += new System.EventHandler(this.SettingsDialog_Load);
|
||||
this.libationFilesGb.ResumeLayout(false);
|
||||
this.libationFilesGb.PerformLayout();
|
||||
this.downloadsInProgressGb.ResumeLayout(false);
|
||||
this.downloadsInProgressGb.PerformLayout();
|
||||
this.decryptInProgressGb.ResumeLayout(false);
|
||||
this.decryptInProgressGb.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Label settingsFileLbl;
|
||||
private System.Windows.Forms.TextBox settingsFileTb;
|
||||
private System.Windows.Forms.Label decryptKeyLbl;
|
||||
private System.Windows.Forms.TextBox decryptKeyTb;
|
||||
private System.Windows.Forms.Label booksLocationLbl;
|
||||
private System.Windows.Forms.TextBox booksLocationTb;
|
||||
private System.Windows.Forms.Button booksLocationSearchBtn;
|
||||
private System.Windows.Forms.Label settingsFileDescLbl;
|
||||
private System.Windows.Forms.Label decryptKeyDescLbl;
|
||||
private System.Windows.Forms.Label booksLocationDescLbl;
|
||||
private System.Windows.Forms.GroupBox libationFilesGb;
|
||||
private System.Windows.Forms.Button libationFilesCustomBtn;
|
||||
private System.Windows.Forms.TextBox libationFilesCustomTb;
|
||||
private System.Windows.Forms.RadioButton libationFilesCustomRb;
|
||||
private System.Windows.Forms.RadioButton libationFilesMyDocsRb;
|
||||
private System.Windows.Forms.RadioButton libationFilesRootRb;
|
||||
private System.Windows.Forms.Label libationFilesDescLbl;
|
||||
private System.Windows.Forms.GroupBox downloadsInProgressGb;
|
||||
private System.Windows.Forms.Label downloadsInProgressDescLbl;
|
||||
private System.Windows.Forms.RadioButton downloadsInProgressWinTempRb;
|
||||
private System.Windows.Forms.RadioButton downloadsInProgressLibationFilesRb;
|
||||
private System.Windows.Forms.GroupBox decryptInProgressGb;
|
||||
private System.Windows.Forms.Label decryptInProgressDescLbl;
|
||||
private System.Windows.Forms.RadioButton decryptInProgressLibationFilesRb;
|
||||
private System.Windows.Forms.RadioButton decryptInProgressWinTempRb;
|
||||
private System.Windows.Forms.Button saveBtn;
|
||||
private System.Windows.Forms.Button cancelBtn;
|
||||
private System.Windows.Forms.Label audibleLocaleLbl;
|
||||
private System.Windows.Forms.ComboBox audibleLocaleCb;
|
||||
}
|
||||
}
|
||||
@@ -1,175 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
using Dinah.Core;
|
||||
using FileManager;
|
||||
|
||||
namespace LibationWinForm
|
||||
{
|
||||
public partial class SettingsDialog : Form
|
||||
{
|
||||
Configuration config { get; } = Configuration.Instance;
|
||||
Func<string, string> desc { get; } = Configuration.GetDescription;
|
||||
string exeRoot { get; }
|
||||
string myDocs { get; }
|
||||
|
||||
bool isFirstLoad;
|
||||
|
||||
public SettingsDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.libationFilesCustomTb.TextChanged += (_, __) =>
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(libationFilesCustomTb.Text))
|
||||
this.libationFilesCustomRb.Checked = true;
|
||||
};
|
||||
|
||||
exeRoot = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(Exe.FileLocationOnDisk), "Libation"));
|
||||
myDocs = Path.GetFullPath(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Libation"));
|
||||
}
|
||||
|
||||
private void SettingsDialog_Load(object sender, EventArgs e)
|
||||
{
|
||||
isFirstLoad = string.IsNullOrWhiteSpace(config.Books);
|
||||
|
||||
this.settingsFileTb.Text = config.Filepath;
|
||||
this.settingsFileDescLbl.Text = desc(nameof(config.Filepath));
|
||||
|
||||
this.decryptKeyTb.Text = config.DecryptKey;
|
||||
this.decryptKeyDescLbl.Text = desc(nameof(config.DecryptKey));
|
||||
|
||||
this.booksLocationTb.Text
|
||||
= !string.IsNullOrWhiteSpace(config.Books)
|
||||
? config.Books
|
||||
: Path.GetDirectoryName(Exe.FileLocationOnDisk);
|
||||
this.booksLocationDescLbl.Text = desc(nameof(config.Books));
|
||||
|
||||
this.audibleLocaleCb.Text
|
||||
= !string.IsNullOrWhiteSpace(config.LocaleCountryCode)
|
||||
? config.LocaleCountryCode
|
||||
: "us";
|
||||
|
||||
libationFilesDescLbl.Text = desc(nameof(config.LibationFiles));
|
||||
this.libationFilesRootRb.Text = "In the same folder that Libation is running from\r\n" + exeRoot;
|
||||
this.libationFilesMyDocsRb.Text = "In My Documents\r\n" + myDocs;
|
||||
if (config.LibationFiles == exeRoot)
|
||||
libationFilesRootRb.Checked = true;
|
||||
else if (config.LibationFiles == myDocs)
|
||||
libationFilesMyDocsRb.Checked = true;
|
||||
else
|
||||
{
|
||||
libationFilesCustomRb.Checked = true;
|
||||
libationFilesCustomTb.Text = config.LibationFiles;
|
||||
}
|
||||
|
||||
this.downloadsInProgressDescLbl.Text = desc(nameof(config.DownloadsInProgressEnum));
|
||||
var winTempDownloadsInProgress = Path.Combine(config.WinTemp, "DownloadsInProgress");
|
||||
this.downloadsInProgressWinTempRb.Text = "In your Windows temporary folder\r\n" + winTempDownloadsInProgress;
|
||||
switch (config.DownloadsInProgressEnum)
|
||||
{
|
||||
case "LibationFiles":
|
||||
downloadsInProgressLibationFilesRb.Checked = true;
|
||||
break;
|
||||
case "WinTemp":
|
||||
default:
|
||||
downloadsInProgressWinTempRb.Checked = true;
|
||||
break;
|
||||
}
|
||||
|
||||
this.decryptInProgressDescLbl.Text = desc(nameof(config.DecryptInProgressEnum));
|
||||
var winTempDecryptInProgress = Path.Combine(config.WinTemp, "DecryptInProgress");
|
||||
this.decryptInProgressWinTempRb.Text = "In your Windows temporary folder\r\n" + winTempDecryptInProgress;
|
||||
switch (config.DecryptInProgressEnum)
|
||||
{
|
||||
case "LibationFiles":
|
||||
decryptInProgressLibationFilesRb.Checked = true;
|
||||
break;
|
||||
case "WinTemp":
|
||||
default:
|
||||
decryptInProgressWinTempRb.Checked = true;
|
||||
break;
|
||||
}
|
||||
|
||||
libationFiles_Changed(this, null);
|
||||
}
|
||||
|
||||
private void libationFiles_Changed(object sender, EventArgs e)
|
||||
{
|
||||
var libationFilesDir
|
||||
= libationFilesRootRb.Checked ? exeRoot
|
||||
: libationFilesMyDocsRb.Checked ? myDocs
|
||||
: libationFilesCustomTb.Text;
|
||||
|
||||
var downloadsInProgress = Path.Combine(libationFilesDir, "DownloadsInProgress");
|
||||
this.downloadsInProgressLibationFilesRb.Text = $"In your Libation Files (ie: program-created files)\r\n{downloadsInProgress}";
|
||||
|
||||
var decryptInProgress = Path.Combine(libationFilesDir, "DecryptInProgress");
|
||||
this.decryptInProgressLibationFilesRb.Text = $"In your Libation Files (ie: program-created files)\r\n{decryptInProgress}";
|
||||
}
|
||||
|
||||
private void booksLocationSearchBtn_Click(object sender, EventArgs e) => selectFolder("Search for books location", this.booksLocationTb);
|
||||
|
||||
private void libationFilesCustomBtn_Click(object sender, EventArgs e) => selectFolder("Search for Libation Files location", this.libationFilesCustomTb);
|
||||
|
||||
private static void selectFolder(string desc, TextBox textbox)
|
||||
{
|
||||
using var dialog = new FolderBrowserDialog { Description = desc, SelectedPath = "" };
|
||||
dialog.ShowDialog();
|
||||
if (!string.IsNullOrWhiteSpace(dialog.SelectedPath))
|
||||
textbox.Text = dialog.SelectedPath;
|
||||
}
|
||||
|
||||
private void saveBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
config.DecryptKey = this.decryptKeyTb.Text;
|
||||
|
||||
var pathsChanged = false;
|
||||
|
||||
if (!Directory.Exists(this.booksLocationTb.Text))
|
||||
MessageBox.Show("Not saving change to Books location. This folder does not exist:\r\n" + this.booksLocationTb.Text);
|
||||
else if (config.Books != this.booksLocationTb.Text)
|
||||
{
|
||||
pathsChanged = true;
|
||||
config.Books = this.booksLocationTb.Text;
|
||||
}
|
||||
|
||||
config.LocaleCountryCode = this.audibleLocaleCb.Text;
|
||||
|
||||
var libationDir
|
||||
= libationFilesRootRb.Checked ? exeRoot
|
||||
: libationFilesMyDocsRb.Checked ? myDocs
|
||||
: libationFilesCustomTb.Text;
|
||||
if (!Directory.Exists(libationDir))
|
||||
MessageBox.Show("Not saving change to Libation Files location. This folder does not exist:\r\n" + libationDir);
|
||||
else if (config.LibationFiles != libationDir)
|
||||
{
|
||||
pathsChanged = true;
|
||||
config.LibationFiles = libationDir;
|
||||
}
|
||||
|
||||
config.DownloadsInProgressEnum = downloadsInProgressLibationFilesRb.Checked ? "LibationFiles" : "WinTemp";
|
||||
config.DecryptInProgressEnum = decryptInProgressLibationFilesRb.Checked ? "LibationFiles" : "WinTemp";
|
||||
|
||||
if (!isFirstLoad && pathsChanged)
|
||||
{
|
||||
var shutdownResult = MessageBox.Show(
|
||||
"You have changed a file path important for this program. All files will remain in their original location; nothing will be moved. It is highly recommended that you restart this program so these changes are handled correctly."
|
||||
+ "\r\n"
|
||||
+ "\r\nClose program?",
|
||||
"Restart program",
|
||||
MessageBoxButtons.YesNo,
|
||||
MessageBoxIcon.Exclamation,
|
||||
MessageBoxDefaultButton.Button1);
|
||||
if (shutdownResult == DialogResult.Yes)
|
||||
{
|
||||
Application.Exit();
|
||||
}
|
||||
}
|
||||
|
||||
this.DialogResult = DialogResult.OK;
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private void cancelBtn_Click(object sender, EventArgs e) => this.Close();
|
||||
}
|
||||
}
|
||||
282
LibationWinForm/UNTESTED/Form1.Designer.cs
generated
@@ -1,282 +0,0 @@
|
||||
namespace LibationWinForm
|
||||
{
|
||||
partial class Form1
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
|
||||
this.gridPanel = new System.Windows.Forms.Panel();
|
||||
this.filterHelpBtn = new System.Windows.Forms.Button();
|
||||
this.filterBtn = new System.Windows.Forms.Button();
|
||||
this.filterSearchTb = new System.Windows.Forms.TextBox();
|
||||
this.menuStrip1 = new System.Windows.Forms.MenuStrip();
|
||||
this.importToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.scanLibraryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.liberateToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.beginBookBackupsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.beginPdfBackupsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.quickFiltersToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.firstFilterIsDefaultToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.editQuickFiltersToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.settingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
|
||||
this.visibleCountLbl = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.springLbl = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.backupsCountsLbl = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.pdfsCountsLbl = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.addFilterBtn = new System.Windows.Forms.Button();
|
||||
this.menuStrip1.SuspendLayout();
|
||||
this.statusStrip1.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// gridPanel
|
||||
//
|
||||
this.gridPanel.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.gridPanel.Location = new System.Drawing.Point(12, 56);
|
||||
this.gridPanel.Name = "gridPanel";
|
||||
this.gridPanel.Size = new System.Drawing.Size(839, 386);
|
||||
this.gridPanel.TabIndex = 5;
|
||||
//
|
||||
// filterHelpBtn
|
||||
//
|
||||
this.filterHelpBtn.Location = new System.Drawing.Point(12, 27);
|
||||
this.filterHelpBtn.Name = "filterHelpBtn";
|
||||
this.filterHelpBtn.Size = new System.Drawing.Size(22, 23);
|
||||
this.filterHelpBtn.TabIndex = 3;
|
||||
this.filterHelpBtn.Text = "?";
|
||||
this.filterHelpBtn.UseVisualStyleBackColor = true;
|
||||
this.filterHelpBtn.Click += new System.EventHandler(this.filterHelpBtn_Click);
|
||||
//
|
||||
// filterBtn
|
||||
//
|
||||
this.filterBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.filterBtn.Location = new System.Drawing.Point(776, 27);
|
||||
this.filterBtn.Name = "filterBtn";
|
||||
this.filterBtn.Size = new System.Drawing.Size(75, 23);
|
||||
this.filterBtn.TabIndex = 2;
|
||||
this.filterBtn.Text = "Filter";
|
||||
this.filterBtn.UseVisualStyleBackColor = true;
|
||||
this.filterBtn.Click += new System.EventHandler(this.filterBtn_Click);
|
||||
//
|
||||
// filterSearchTb
|
||||
//
|
||||
this.filterSearchTb.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.filterSearchTb.Location = new System.Drawing.Point(186, 29);
|
||||
this.filterSearchTb.Name = "filterSearchTb";
|
||||
this.filterSearchTb.Size = new System.Drawing.Size(584, 20);
|
||||
this.filterSearchTb.TabIndex = 1;
|
||||
this.filterSearchTb.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.filterSearchTb_KeyPress);
|
||||
//
|
||||
// menuStrip1
|
||||
//
|
||||
this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.importToolStripMenuItem,
|
||||
this.liberateToolStripMenuItem,
|
||||
this.quickFiltersToolStripMenuItem,
|
||||
this.settingsToolStripMenuItem});
|
||||
this.menuStrip1.Location = new System.Drawing.Point(0, 0);
|
||||
this.menuStrip1.Name = "menuStrip1";
|
||||
this.menuStrip1.Size = new System.Drawing.Size(863, 24);
|
||||
this.menuStrip1.TabIndex = 0;
|
||||
this.menuStrip1.Text = "menuStrip1";
|
||||
//
|
||||
// importToolStripMenuItem
|
||||
//
|
||||
this.importToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.scanLibraryToolStripMenuItem});
|
||||
this.importToolStripMenuItem.Name = "importToolStripMenuItem";
|
||||
this.importToolStripMenuItem.Size = new System.Drawing.Size(55, 20);
|
||||
this.importToolStripMenuItem.Text = "&Import";
|
||||
//
|
||||
// scanLibraryToolStripMenuItem
|
||||
//
|
||||
this.scanLibraryToolStripMenuItem.Name = "scanLibraryToolStripMenuItem";
|
||||
this.scanLibraryToolStripMenuItem.Size = new System.Drawing.Size(138, 22);
|
||||
this.scanLibraryToolStripMenuItem.Text = "Scan &Library";
|
||||
this.scanLibraryToolStripMenuItem.Click += new System.EventHandler(this.scanLibraryToolStripMenuItem_Click);
|
||||
//
|
||||
// liberateToolStripMenuItem
|
||||
//
|
||||
this.liberateToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.beginBookBackupsToolStripMenuItem,
|
||||
this.beginPdfBackupsToolStripMenuItem});
|
||||
this.liberateToolStripMenuItem.Name = "liberateToolStripMenuItem";
|
||||
this.liberateToolStripMenuItem.Size = new System.Drawing.Size(61, 20);
|
||||
this.liberateToolStripMenuItem.Text = "&Liberate";
|
||||
//
|
||||
// beginBookBackupsToolStripMenuItem
|
||||
//
|
||||
this.beginBookBackupsToolStripMenuItem.Name = "beginBookBackupsToolStripMenuItem";
|
||||
this.beginBookBackupsToolStripMenuItem.Size = new System.Drawing.Size(248, 22);
|
||||
this.beginBookBackupsToolStripMenuItem.Text = "Begin &Book and PDF Backups: {0}";
|
||||
this.beginBookBackupsToolStripMenuItem.Click += new System.EventHandler(this.beginBookBackupsToolStripMenuItem_Click);
|
||||
//
|
||||
// beginPdfBackupsToolStripMenuItem
|
||||
//
|
||||
this.beginPdfBackupsToolStripMenuItem.Name = "beginPdfBackupsToolStripMenuItem";
|
||||
this.beginPdfBackupsToolStripMenuItem.Size = new System.Drawing.Size(248, 22);
|
||||
this.beginPdfBackupsToolStripMenuItem.Text = "Begin &PDF Only Backups: {0}";
|
||||
this.beginPdfBackupsToolStripMenuItem.Click += new System.EventHandler(this.beginPdfBackupsToolStripMenuItem_Click);
|
||||
//
|
||||
// quickFiltersToolStripMenuItem
|
||||
//
|
||||
this.quickFiltersToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.firstFilterIsDefaultToolStripMenuItem,
|
||||
this.editQuickFiltersToolStripMenuItem,
|
||||
this.toolStripSeparator1});
|
||||
this.quickFiltersToolStripMenuItem.Name = "quickFiltersToolStripMenuItem";
|
||||
this.quickFiltersToolStripMenuItem.Size = new System.Drawing.Size(84, 20);
|
||||
this.quickFiltersToolStripMenuItem.Text = "Quick &Filters";
|
||||
//
|
||||
// firstFilterIsDefaultToolStripMenuItem
|
||||
//
|
||||
this.firstFilterIsDefaultToolStripMenuItem.Name = "firstFilterIsDefaultToolStripMenuItem";
|
||||
this.firstFilterIsDefaultToolStripMenuItem.Size = new System.Drawing.Size(256, 22);
|
||||
this.firstFilterIsDefaultToolStripMenuItem.Text = "Start Libation with 1st filter &Default";
|
||||
this.firstFilterIsDefaultToolStripMenuItem.Click += new System.EventHandler(this.FirstFilterIsDefaultToolStripMenuItem_Click);
|
||||
//
|
||||
// editQuickFiltersToolStripMenuItem
|
||||
//
|
||||
this.editQuickFiltersToolStripMenuItem.Name = "editQuickFiltersToolStripMenuItem";
|
||||
this.editQuickFiltersToolStripMenuItem.Size = new System.Drawing.Size(256, 22);
|
||||
this.editQuickFiltersToolStripMenuItem.Text = "&Edit quick filters";
|
||||
this.editQuickFiltersToolStripMenuItem.Click += new System.EventHandler(this.EditQuickFiltersToolStripMenuItem_Click);
|
||||
//
|
||||
// toolStripSeparator1
|
||||
//
|
||||
this.toolStripSeparator1.Name = "toolStripSeparator1";
|
||||
this.toolStripSeparator1.Size = new System.Drawing.Size(253, 6);
|
||||
//
|
||||
// settingsToolStripMenuItem
|
||||
//
|
||||
this.settingsToolStripMenuItem.Name = "settingsToolStripMenuItem";
|
||||
this.settingsToolStripMenuItem.Size = new System.Drawing.Size(61, 20);
|
||||
this.settingsToolStripMenuItem.Text = "&Settings";
|
||||
this.settingsToolStripMenuItem.Click += new System.EventHandler(this.settingsToolStripMenuItem_Click);
|
||||
//
|
||||
// statusStrip1
|
||||
//
|
||||
this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.visibleCountLbl,
|
||||
this.springLbl,
|
||||
this.backupsCountsLbl,
|
||||
this.pdfsCountsLbl});
|
||||
this.statusStrip1.Location = new System.Drawing.Point(0, 445);
|
||||
this.statusStrip1.Name = "statusStrip1";
|
||||
this.statusStrip1.Size = new System.Drawing.Size(863, 22);
|
||||
this.statusStrip1.TabIndex = 6;
|
||||
this.statusStrip1.Text = "statusStrip1";
|
||||
//
|
||||
// visibleCountLbl
|
||||
//
|
||||
this.visibleCountLbl.Name = "visibleCountLbl";
|
||||
this.visibleCountLbl.Size = new System.Drawing.Size(61, 17);
|
||||
this.visibleCountLbl.Text = "Visible: {0}";
|
||||
//
|
||||
// springLbl
|
||||
//
|
||||
this.springLbl.Name = "springLbl";
|
||||
this.springLbl.Size = new System.Drawing.Size(232, 17);
|
||||
this.springLbl.Spring = true;
|
||||
//
|
||||
// backupsCountsLbl
|
||||
//
|
||||
this.backupsCountsLbl.Name = "backupsCountsLbl";
|
||||
this.backupsCountsLbl.Size = new System.Drawing.Size(336, 17);
|
||||
this.backupsCountsLbl.Text = "BACKUPS: No progress: {0} Encrypted: {1} Fully backed up: {2}";
|
||||
//
|
||||
// pdfsCountsLbl
|
||||
//
|
||||
this.pdfsCountsLbl.Name = "pdfsCountsLbl";
|
||||
this.pdfsCountsLbl.Size = new System.Drawing.Size(219, 17);
|
||||
this.pdfsCountsLbl.Text = "| PDFs: NOT d/l\'ed: {0} Downloaded: {1}";
|
||||
//
|
||||
// addFilterBtn
|
||||
//
|
||||
this.addFilterBtn.Location = new System.Drawing.Point(40, 27);
|
||||
this.addFilterBtn.Name = "addFilterBtn";
|
||||
this.addFilterBtn.Size = new System.Drawing.Size(140, 23);
|
||||
this.addFilterBtn.TabIndex = 4;
|
||||
this.addFilterBtn.Text = "Add To Quick Filters";
|
||||
this.addFilterBtn.UseVisualStyleBackColor = true;
|
||||
this.addFilterBtn.Click += new System.EventHandler(this.AddFilterBtn_Click);
|
||||
//
|
||||
// Form1
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(863, 467);
|
||||
this.Controls.Add(this.filterBtn);
|
||||
this.Controls.Add(this.addFilterBtn);
|
||||
this.Controls.Add(this.filterSearchTb);
|
||||
this.Controls.Add(this.filterHelpBtn);
|
||||
this.Controls.Add(this.statusStrip1);
|
||||
this.Controls.Add(this.gridPanel);
|
||||
this.Controls.Add(this.menuStrip1);
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.MainMenuStrip = this.menuStrip1;
|
||||
this.Name = "Form1";
|
||||
this.Text = "Libation: Liberate your Library";
|
||||
this.Load += new System.EventHandler(this.Form1_Load);
|
||||
this.menuStrip1.ResumeLayout(false);
|
||||
this.menuStrip1.PerformLayout();
|
||||
this.statusStrip1.ResumeLayout(false);
|
||||
this.statusStrip1.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
private System.Windows.Forms.Panel gridPanel;
|
||||
private System.Windows.Forms.MenuStrip menuStrip1;
|
||||
private System.Windows.Forms.ToolStripMenuItem importToolStripMenuItem;
|
||||
private System.Windows.Forms.StatusStrip statusStrip1;
|
||||
private System.Windows.Forms.ToolStripStatusLabel springLbl;
|
||||
private System.Windows.Forms.ToolStripStatusLabel visibleCountLbl;
|
||||
private System.Windows.Forms.ToolStripMenuItem liberateToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripStatusLabel backupsCountsLbl;
|
||||
private System.Windows.Forms.ToolStripMenuItem beginBookBackupsToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripStatusLabel pdfsCountsLbl;
|
||||
private System.Windows.Forms.ToolStripMenuItem beginPdfBackupsToolStripMenuItem;
|
||||
private System.Windows.Forms.TextBox filterSearchTb;
|
||||
private System.Windows.Forms.Button filterBtn;
|
||||
private System.Windows.Forms.Button filterHelpBtn;
|
||||
private System.Windows.Forms.ToolStripMenuItem settingsToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem scanLibraryToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem quickFiltersToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem firstFilterIsDefaultToolStripMenuItem;
|
||||
private System.Windows.Forms.Button addFilterBtn;
|
||||
private System.Windows.Forms.ToolStripMenuItem editQuickFiltersToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
|
||||
}
|
||||
}
|
||||
|
||||
201
LibationWinForm/UNTESTED/ProductsGrid.Designer.cs
generated
@@ -1,201 +0,0 @@
|
||||
namespace LibationWinForm
|
||||
{
|
||||
partial class ProductsGrid
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
this.gridEntryBindingSource = new System.Windows.Forms.BindingSource(this.components);
|
||||
this.gridEntryDataGridView = new System.Windows.Forms.DataGridView();
|
||||
this.dataGridViewImageColumn1 = new System.Windows.Forms.DataGridViewImageColumn();
|
||||
this.dataGridViewTextBoxColumn1 = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.dataGridViewTextBoxColumn2 = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.dataGridViewTextBoxColumn3 = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.dataGridViewTextBoxColumn4 = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.dataGridViewTextBoxColumn5 = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.dataGridViewTextBoxColumn6 = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.dataGridViewTextBoxColumn7 = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.dataGridViewTextBoxColumn8 = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.dataGridViewTextBoxColumn9 = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.dataGridViewTextBoxColumn10 = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.dataGridViewTextBoxColumn11 = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.dataGridViewTextBoxColumn12 = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
((System.ComponentModel.ISupportInitialize)(this.gridEntryBindingSource)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.gridEntryDataGridView)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// gridEntryBindingSource
|
||||
//
|
||||
this.gridEntryBindingSource.DataSource = typeof(LibationWinForm.GridEntry);
|
||||
//
|
||||
// gridEntryDataGridView
|
||||
//
|
||||
this.gridEntryDataGridView.AutoGenerateColumns = false;
|
||||
this.gridEntryDataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
|
||||
this.gridEntryDataGridView.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
|
||||
this.dataGridViewImageColumn1,
|
||||
this.dataGridViewTextBoxColumn1,
|
||||
this.dataGridViewTextBoxColumn2,
|
||||
this.dataGridViewTextBoxColumn3,
|
||||
this.dataGridViewTextBoxColumn4,
|
||||
this.dataGridViewTextBoxColumn5,
|
||||
this.dataGridViewTextBoxColumn6,
|
||||
this.dataGridViewTextBoxColumn7,
|
||||
this.dataGridViewTextBoxColumn8,
|
||||
this.dataGridViewTextBoxColumn9,
|
||||
this.dataGridViewTextBoxColumn10,
|
||||
this.dataGridViewTextBoxColumn11,
|
||||
this.dataGridViewTextBoxColumn12});
|
||||
this.gridEntryDataGridView.DataSource = this.gridEntryBindingSource;
|
||||
this.gridEntryDataGridView.Location = new System.Drawing.Point(54, 58);
|
||||
this.gridEntryDataGridView.Name = "gridEntryDataGridView";
|
||||
this.gridEntryDataGridView.Size = new System.Drawing.Size(300, 220);
|
||||
this.gridEntryDataGridView.TabIndex = 0;
|
||||
//
|
||||
// dataGridViewImageColumn1
|
||||
//
|
||||
this.dataGridViewImageColumn1.DataPropertyName = "Cover";
|
||||
this.dataGridViewImageColumn1.HeaderText = "Cover";
|
||||
this.dataGridViewImageColumn1.Name = "dataGridViewImageColumn1";
|
||||
this.dataGridViewImageColumn1.ReadOnly = true;
|
||||
//
|
||||
// dataGridViewTextBoxColumn1
|
||||
//
|
||||
this.dataGridViewTextBoxColumn1.DataPropertyName = "Title";
|
||||
this.dataGridViewTextBoxColumn1.HeaderText = "Title";
|
||||
this.dataGridViewTextBoxColumn1.Name = "dataGridViewTextBoxColumn1";
|
||||
this.dataGridViewTextBoxColumn1.ReadOnly = true;
|
||||
//
|
||||
// dataGridViewTextBoxColumn2
|
||||
//
|
||||
this.dataGridViewTextBoxColumn2.DataPropertyName = "Authors";
|
||||
this.dataGridViewTextBoxColumn2.HeaderText = "Authors";
|
||||
this.dataGridViewTextBoxColumn2.Name = "dataGridViewTextBoxColumn2";
|
||||
this.dataGridViewTextBoxColumn2.ReadOnly = true;
|
||||
//
|
||||
// dataGridViewTextBoxColumn3
|
||||
//
|
||||
this.dataGridViewTextBoxColumn3.DataPropertyName = "Narrators";
|
||||
this.dataGridViewTextBoxColumn3.HeaderText = "Narrators";
|
||||
this.dataGridViewTextBoxColumn3.Name = "dataGridViewTextBoxColumn3";
|
||||
this.dataGridViewTextBoxColumn3.ReadOnly = true;
|
||||
//
|
||||
// dataGridViewTextBoxColumn4
|
||||
//
|
||||
this.dataGridViewTextBoxColumn4.DataPropertyName = "Length";
|
||||
this.dataGridViewTextBoxColumn4.HeaderText = "Length";
|
||||
this.dataGridViewTextBoxColumn4.Name = "dataGridViewTextBoxColumn4";
|
||||
this.dataGridViewTextBoxColumn4.ReadOnly = true;
|
||||
//
|
||||
// dataGridViewTextBoxColumn5
|
||||
//
|
||||
this.dataGridViewTextBoxColumn5.DataPropertyName = "Series";
|
||||
this.dataGridViewTextBoxColumn5.HeaderText = "Series";
|
||||
this.dataGridViewTextBoxColumn5.Name = "dataGridViewTextBoxColumn5";
|
||||
this.dataGridViewTextBoxColumn5.ReadOnly = true;
|
||||
//
|
||||
// dataGridViewTextBoxColumn6
|
||||
//
|
||||
this.dataGridViewTextBoxColumn6.DataPropertyName = "Description";
|
||||
this.dataGridViewTextBoxColumn6.HeaderText = "Description";
|
||||
this.dataGridViewTextBoxColumn6.Name = "dataGridViewTextBoxColumn6";
|
||||
this.dataGridViewTextBoxColumn6.ReadOnly = true;
|
||||
//
|
||||
// dataGridViewTextBoxColumn7
|
||||
//
|
||||
this.dataGridViewTextBoxColumn7.DataPropertyName = "Category";
|
||||
this.dataGridViewTextBoxColumn7.HeaderText = "Category";
|
||||
this.dataGridViewTextBoxColumn7.Name = "dataGridViewTextBoxColumn7";
|
||||
this.dataGridViewTextBoxColumn7.ReadOnly = true;
|
||||
//
|
||||
// dataGridViewTextBoxColumn8
|
||||
//
|
||||
this.dataGridViewTextBoxColumn8.DataPropertyName = "Product_Rating";
|
||||
this.dataGridViewTextBoxColumn8.HeaderText = "Product_Rating";
|
||||
this.dataGridViewTextBoxColumn8.Name = "dataGridViewTextBoxColumn8";
|
||||
this.dataGridViewTextBoxColumn8.ReadOnly = true;
|
||||
//
|
||||
// dataGridViewTextBoxColumn9
|
||||
//
|
||||
this.dataGridViewTextBoxColumn9.DataPropertyName = "Purchase_Date";
|
||||
this.dataGridViewTextBoxColumn9.HeaderText = "Purchase_Date";
|
||||
this.dataGridViewTextBoxColumn9.Name = "dataGridViewTextBoxColumn9";
|
||||
this.dataGridViewTextBoxColumn9.ReadOnly = true;
|
||||
//
|
||||
// dataGridViewTextBoxColumn10
|
||||
//
|
||||
this.dataGridViewTextBoxColumn10.DataPropertyName = "My_Rating";
|
||||
this.dataGridViewTextBoxColumn10.HeaderText = "My_Rating";
|
||||
this.dataGridViewTextBoxColumn10.Name = "dataGridViewTextBoxColumn10";
|
||||
this.dataGridViewTextBoxColumn10.ReadOnly = true;
|
||||
//
|
||||
// dataGridViewTextBoxColumn11
|
||||
//
|
||||
this.dataGridViewTextBoxColumn11.DataPropertyName = "Misc";
|
||||
this.dataGridViewTextBoxColumn11.HeaderText = "Misc";
|
||||
this.dataGridViewTextBoxColumn11.Name = "dataGridViewTextBoxColumn11";
|
||||
this.dataGridViewTextBoxColumn11.ReadOnly = true;
|
||||
//
|
||||
// dataGridViewTextBoxColumn12
|
||||
//
|
||||
this.dataGridViewTextBoxColumn12.DataPropertyName = "Download_Status";
|
||||
this.dataGridViewTextBoxColumn12.HeaderText = "Download_Status";
|
||||
this.dataGridViewTextBoxColumn12.Name = "dataGridViewTextBoxColumn12";
|
||||
this.dataGridViewTextBoxColumn12.ReadOnly = true;
|
||||
//
|
||||
// ProductsGrid
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.Controls.Add(this.gridEntryDataGridView);
|
||||
this.Name = "ProductsGrid";
|
||||
this.Size = new System.Drawing.Size(434, 329);
|
||||
((System.ComponentModel.ISupportInitialize)(this.gridEntryBindingSource)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.gridEntryDataGridView)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.BindingSource gridEntryBindingSource;
|
||||
private System.Windows.Forms.DataGridView gridEntryDataGridView;
|
||||
private System.Windows.Forms.DataGridViewImageColumn dataGridViewImageColumn1;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn1;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn2;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn3;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn4;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn5;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn6;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn7;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn8;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn9;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn10;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn11;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn12;
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using Serilog;
|
||||
|
||||
namespace LibationWinForm
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
|
||||
if (!createSettings())
|
||||
return;
|
||||
|
||||
init();
|
||||
|
||||
Application.Run(new Form1());
|
||||
}
|
||||
|
||||
private static bool createSettings()
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(FileManager.Configuration.Instance.Books))
|
||||
return true;
|
||||
|
||||
var welcomeText = @"
|
||||
This appears to be your first time using Libation. Welcome.
|
||||
Please fill in a few settings on the following page. You can also change these settings later.
|
||||
|
||||
After you make your selections, get started by importing your library.
|
||||
Go to Import > Scan Library
|
||||
".Trim();
|
||||
MessageBox.Show(welcomeText, "Welcome to Libation", MessageBoxButtons.OK);
|
||||
var dialogResult = new SettingsDialog().ShowDialog();
|
||||
if (dialogResult != DialogResult.OK)
|
||||
{
|
||||
MessageBox.Show("Initial set up cancelled.", "Cancelled", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void init()
|
||||
{
|
||||
var logPath = System.IO.Path.Combine(FileManager.Configuration.Instance.LibationFiles, "Log.log");
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
.MinimumLevel.Debug()
|
||||
.WriteTo.File(logPath, rollingInterval: RollingInterval.Month)
|
||||
.CreateLogger();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<OutputType>Library</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<ApplicationIcon>libation.ico</ApplicationIcon>
|
||||
<AssemblyName>Libation</AssemblyName>
|
||||
|
||||
<PublishTrimmed>true</PublishTrimmed>
|
||||
<PublishReadyToRun>true</PublishReadyToRun>
|
||||
@@ -24,12 +23,30 @@
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="UNTESTED\Dialogs\LibationFilesDialog.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Update="UNTESTED\Dialogs\LibationFilesDialog.Designer.cs">
|
||||
<DependentUpon>LibationFilesDialog.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="UNTESTED\Dialogs\SettingsDialog.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Update="UNTESTED\Dialogs\SettingsDialog.Designer.cs">
|
||||
<DependentUpon>SettingsDialog.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="UNTESTED\Dialogs\IndexLibraryDialog.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Update="UNTESTED\Dialogs\IndexLibraryDialog.Designer.cs">
|
||||
<DependentUpon>IndexLibraryDialog.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="UNTESTED\Dialogs\SetupDialog.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Update="UNTESTED\Dialogs\SetupDialog.Designer.cs">
|
||||
<DependentUpon>SetupDialog.cs</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -37,6 +54,15 @@
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="UNTESTED\Dialogs\LibationFilesDialog.resx">
|
||||
<DependentUpon>LibationFilesDialog.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="UNTESTED\Dialogs\SettingsDialog.resx">
|
||||
<DependentUpon>SettingsDialog.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="UNTESTED\Dialogs\SetupDialog.resx">
|
||||
<DependentUpon>SetupDialog.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -6,5 +6,5 @@
|
||||
cause the file to be unrecognizable by the program.
|
||||
-->
|
||||
<GenericObjectDataSource DisplayName="GridEntry" Version="1.0" xmlns="urn:schemas-microsoft-com:xml-msdatasource">
|
||||
<TypeInfo>WinFormsDesigner.GridEntry, LibationWinForm, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null</TypeInfo>
|
||||
<TypeInfo>LibationWinForms.GridEntry, LibationWinForms, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null</TypeInfo>
|
||||
</GenericObjectDataSource>
|
||||
@@ -8,7 +8,7 @@
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace LibationWinForm.Properties {
|
||||
namespace LibationWinForms.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace LibationWinForm.Properties {
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("LibationWinForm.Properties.Resources", typeof(Resources).Assembly);
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("LibationWinForms.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
|
Before Width: | Height: | Size: 314 B After Width: | Height: | Size: 314 B |
|
Before Width: | Height: | Size: 573 B After Width: | Height: | Size: 573 B |
|
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 92 KiB |
@@ -1,4 +1,4 @@
|
||||
namespace LibationWinForm.BookLiberation
|
||||
namespace LibationWinForms.BookLiberation
|
||||
{
|
||||
partial class AutomatedBackupsForm
|
||||
{
|
||||
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using Dinah.Core.Windows.Forms;
|
||||
|
||||
namespace LibationWinForms.BookLiberation
|
||||
{
|
||||
public partial class AutomatedBackupsForm : Form
|
||||
{
|
||||
public bool KeepGoingVisible
|
||||
{
|
||||
get => keepGoingCb.Visible;
|
||||
set => keepGoingCb.Visible = value;
|
||||
}
|
||||
|
||||
public bool KeepGoingChecked => keepGoingCb.Checked;
|
||||
|
||||
public bool KeepGoing
|
||||
=> keepGoingCb.Visible
|
||||
&& keepGoingCb.Enabled
|
||||
&& keepGoingCb.Checked;
|
||||
|
||||
public AutomatedBackupsForm()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void AppendError(Exception ex)
|
||||
{
|
||||
Serilog.Log.Logger.Error(ex, "Automated backup: error");
|
||||
appendText("ERROR: " + ex.Message);
|
||||
}
|
||||
public void AppendText(string text)
|
||||
{
|
||||
Serilog.Log.Logger.Information($"Automated backup: {text}");
|
||||
appendText(text);
|
||||
}
|
||||
private void appendText(string text)
|
||||
=> logTb.UIThread(() => logTb.AppendText($"{DateTime.Now} {text}{Environment.NewLine}"));
|
||||
|
||||
public void FinalizeUI()
|
||||
{
|
||||
keepGoingCb.Enabled = false;
|
||||
logTb.AppendText("");
|
||||
AppendText("DONE");
|
||||
}
|
||||
|
||||
private void AutomatedBackupsForm_FormClosing(object sender, FormClosingEventArgs e) => keepGoingCb.Checked = false;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace LibationWinForm.BookLiberation
|
||||
namespace LibationWinForms.BookLiberation
|
||||
{
|
||||
partial class DecryptForm
|
||||
{
|
||||
@@ -4,22 +4,23 @@ using Dinah.Core.Drawing;
|
||||
using Dinah.Core.IO;
|
||||
using Dinah.Core.Windows.Forms;
|
||||
|
||||
namespace LibationWinForm.BookLiberation
|
||||
namespace LibationWinForms.BookLiberation
|
||||
{
|
||||
public partial class DecryptForm : Form
|
||||
{
|
||||
public DecryptForm()
|
||||
public DecryptForm()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
System.IO.TextWriter origOut = Console.Out;
|
||||
System.IO.TextWriter origOut { get; } = Console.Out;
|
||||
private void DecryptForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
// redirect Console.WriteLine to console, textbox
|
||||
System.IO.TextWriter origOut = Console.Out;
|
||||
var controlWriter = new RichTextBoxTextWriter(this.rtbLog);
|
||||
var multiLogger = new MultiTextWriter(origOut, controlWriter);
|
||||
var multiLogger = new MultiTextWriter(
|
||||
origOut,
|
||||
new RichTextBoxTextWriter(this.rtbLog),
|
||||
new SerilogTextWriter());
|
||||
Console.SetOut(multiLogger);
|
||||
}
|
||||
|
||||
@@ -58,13 +59,6 @@ namespace LibationWinForm.BookLiberation
|
||||
public void SetCoverImage(byte[] coverBytes)
|
||||
=> pictureBox1.UIThread(() => pictureBox1.Image = ImageReader.ToImage(coverBytes));
|
||||
|
||||
public static void AppendError(Exception ex) => AppendText("ERROR: " + ex.Message);
|
||||
public static void AppendText(string text) =>
|
||||
// redirected to log textbox
|
||||
Console.WriteLine($"{DateTime.Now} {text}")
|
||||
//logTb.UIThread(() => logTb.AppendText($"{DateTime.Now} {text}{Environment.NewLine}"))
|
||||
;
|
||||
|
||||
public void UpdateProgress(int percentage) => progressBar1.UIThread(() => progressBar1.Value = percentage);
|
||||
public void UpdateProgress(int percentage) => progressBar1.UIThread(() => progressBar1.Value = percentage);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace LibationWinForm.BookLiberation
|
||||
namespace LibationWinForms.BookLiberation
|
||||
{
|
||||
partial class DownloadForm
|
||||
{
|
||||
@@ -2,7 +2,7 @@
|
||||
using System.Windows.Forms;
|
||||
using Dinah.Core.Windows.Forms;
|
||||
|
||||
namespace LibationWinForm.BookLiberation
|
||||
namespace LibationWinForms.BookLiberation
|
||||
{
|
||||
public partial class DownloadForm : Form
|
||||
{
|
||||
@@ -1,8 +1,10 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using DataLayer;
|
||||
using Dinah.Core.ErrorHandling;
|
||||
using FileLiberator;
|
||||
|
||||
namespace LibationWinForm.BookLiberation
|
||||
namespace LibationWinForms.BookLiberation
|
||||
{
|
||||
// matches a file processor with a form
|
||||
public static class ProcessorAutomationController
|
||||
@@ -12,37 +14,38 @@ namespace LibationWinForm.BookLiberation
|
||||
// 1) we can't forget to do it
|
||||
// 2) we can't accidentally do it mult times becaues we lost track of complexity
|
||||
//
|
||||
public static BackupBook GetWiredUpBackupBook()
|
||||
public static BackupBook GetWiredUpBackupBook(EventHandler<LibraryBook> completedAction = null)
|
||||
{
|
||||
var backupBook = new BackupBook();
|
||||
|
||||
backupBook.DownloadBook.Begin += (_, __) => wireUpDownloadable(backupBook.DownloadBook);
|
||||
backupBook.DecryptBook.Begin += (_, __) => wireUpDecryptable(backupBook.DecryptBook);
|
||||
backupBook.DownloadPdf.Begin += (_, __) => wireUpDecryptable(backupBook.DecryptBook);
|
||||
backupBook.DownloadBook.Begin += (_, __) => wireUpEvents(backupBook.DownloadBook);
|
||||
backupBook.DecryptBook.Begin += (_, __) => wireUpEvents(backupBook.DecryptBook);
|
||||
backupBook.DownloadPdf.Begin += (_, __) => wireUpEvents(backupBook.DownloadPdf);
|
||||
|
||||
return backupBook;
|
||||
if (completedAction != null)
|
||||
{
|
||||
backupBook.DownloadBook.Completed += completedAction;
|
||||
backupBook.DecryptBook.Completed += completedAction;
|
||||
backupBook.DownloadPdf.Completed += completedAction;
|
||||
}
|
||||
|
||||
return backupBook;
|
||||
}
|
||||
public static DecryptBook GetWiredUpDecryptBook()
|
||||
{
|
||||
var decryptBook = new DecryptBook();
|
||||
decryptBook.Begin += (_, __) => wireUpDecryptable(decryptBook);
|
||||
return decryptBook;
|
||||
}
|
||||
public static DownloadBook GetWiredUpDownloadBook()
|
||||
{
|
||||
var downloadBook = new DownloadBook();
|
||||
downloadBook.Begin += (_, __) => wireUpDownloadable(downloadBook);
|
||||
return downloadBook;
|
||||
}
|
||||
public static DownloadPdf GetWiredUpDownloadPdf()
|
||||
|
||||
public static DownloadPdf GetWiredUpDownloadPdf(EventHandler<LibraryBook> completedAction = null)
|
||||
{
|
||||
var downloadPdf = new DownloadPdf();
|
||||
downloadPdf.Begin += (_, __) => wireUpDownloadable(downloadPdf);
|
||||
|
||||
downloadPdf.Begin += (_, __) => wireUpEvents(downloadPdf);
|
||||
|
||||
if (completedAction != null)
|
||||
downloadPdf.Completed += completedAction;
|
||||
|
||||
return downloadPdf;
|
||||
}
|
||||
|
||||
// subscribed to Begin event because a new form should be created+processed+closed on each iteration
|
||||
private static void wireUpDownloadable(IDownloadable downloadable)
|
||||
private static void wireUpEvents(IDownloadable downloadable)
|
||||
{
|
||||
#region create form
|
||||
var downloadDialog = new DownloadForm();
|
||||
@@ -82,7 +85,7 @@ namespace LibationWinForm.BookLiberation
|
||||
|
||||
// unless we dispose, if the form is created but un-used/never-shown then weird UI stuff can happen
|
||||
// also, since event unsubscribe occurs on FormClosing and an unused form is never closed, then the events will never be unsubscribed
|
||||
void dialogDispose(object _, string __)
|
||||
void dialogDispose(object _, object __)
|
||||
{
|
||||
if (!downloadDialog.IsDisposed)
|
||||
downloadDialog.Dispose();
|
||||
@@ -106,7 +109,7 @@ namespace LibationWinForm.BookLiberation
|
||||
}
|
||||
|
||||
// subscribed to Begin event because a new form should be created+processed+closed on each iteration
|
||||
private static void wireUpDecryptable(IDecryptable decryptBook)
|
||||
private static void wireUpEvents(IDecryptable decryptBook)
|
||||
{
|
||||
#region create form
|
||||
var decryptDialog = new DecryptForm();
|
||||
@@ -153,17 +156,23 @@ namespace LibationWinForm.BookLiberation
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static async Task RunAutomaticDownload(IDownloadable downloadable)
|
||||
public static async Task RunAutomaticDownloadAsync(IDownloadable downloadable)
|
||||
{
|
||||
AutomatedBackupsForm automatedBackupsForm = attachToBackupsForm(downloadable);
|
||||
await runBackupLoopAsync(downloadable, automatedBackupsForm);
|
||||
}
|
||||
|
||||
private static AutomatedBackupsForm attachToBackupsForm(IDownloadable downloadable)
|
||||
{
|
||||
#region create form
|
||||
var automatedBackupsForm = new AutomatedBackupsForm();
|
||||
#endregion
|
||||
|
||||
#region define how model actions will affect form behavior
|
||||
void begin(object _, string str) => automatedBackupsForm.AppendText("Begin: " + str);
|
||||
void begin(object _, LibraryBook libraryBook) => automatedBackupsForm.AppendText($"Begin: {libraryBook.Book}");
|
||||
void statusUpdate(object _, string str) => automatedBackupsForm.AppendText("- " + str);
|
||||
// extra line after book is completely finished
|
||||
void completed(object _, string str) => automatedBackupsForm.AppendText("Completed: " + str + Environment.NewLine);
|
||||
void completed(object _, LibraryBook libraryBook) => automatedBackupsForm.AppendText($"Completed: {libraryBook.Book}{Environment.NewLine}");
|
||||
#endregion
|
||||
|
||||
#region subscribe new form to model's events
|
||||
@@ -182,42 +191,55 @@ namespace LibationWinForm.BookLiberation
|
||||
};
|
||||
#endregion
|
||||
|
||||
await runBackupLoop(downloadable, automatedBackupsForm);
|
||||
return automatedBackupsForm;
|
||||
}
|
||||
|
||||
public static async Task RunAutomaticBackup(BackupBook backupBook)
|
||||
public static async Task RunAutomaticBackupAsync(BackupBook backupBook)
|
||||
{
|
||||
var automatedBackupsForm = attachToBackupsForm(backupBook);
|
||||
await runBackupLoopAsync(backupBook, automatedBackupsForm);
|
||||
}
|
||||
|
||||
public static async Task RunSingleBackupAsync(BackupBook backupBook, string productId)
|
||||
{
|
||||
var automatedBackupsForm = attachToBackupsForm(backupBook);
|
||||
automatedBackupsForm.KeepGoingVisible = false;
|
||||
await runSingleBackupAsync(backupBook, automatedBackupsForm, productId);
|
||||
}
|
||||
|
||||
private static AutomatedBackupsForm attachToBackupsForm(BackupBook backupBook)
|
||||
{
|
||||
#region create form
|
||||
var automatedBackupsForm = new AutomatedBackupsForm();
|
||||
#endregion
|
||||
|
||||
#region define how model actions will affect form behavior
|
||||
void downloadBookBegin(object _, string str) => automatedBackupsForm.AppendText("DownloadStep_Begin: " + str);
|
||||
void downloadBookBegin(object _, LibraryBook libraryBook) => automatedBackupsForm.AppendText($"Download Step, Begin: {libraryBook.Book}");
|
||||
void statusUpdate(object _, string str) => automatedBackupsForm.AppendText("- " + str);
|
||||
void downloadBookCompleted(object _, string str) => automatedBackupsForm.AppendText("DownloadStep_Completed: " + str);
|
||||
void decryptBookBegin(object _, string str) => automatedBackupsForm.AppendText("DecryptStep_Begin: " + str);
|
||||
void downloadBookCompleted(object _, LibraryBook libraryBook) => automatedBackupsForm.AppendText($"Download Step, Completed: {libraryBook.Book}");
|
||||
void decryptBookBegin(object _, LibraryBook libraryBook) => automatedBackupsForm.AppendText($"Decrypt Step, Begin: {libraryBook.Book}");
|
||||
// extra line after book is completely finished
|
||||
void decryptBookCompleted(object _, string str) => automatedBackupsForm.AppendText("DecryptStep_Completed: " + str + Environment.NewLine);
|
||||
void downloadPdfBegin(object _, string str) => automatedBackupsForm.AppendText("PdfStep_Begin: " + str);
|
||||
// extra line after book is completely finished
|
||||
void downloadPdfCompleted(object _, string str) => automatedBackupsForm.AppendText("PdfStep_Completed: " + str + Environment.NewLine);
|
||||
#endregion
|
||||
void decryptBookCompleted(object _, LibraryBook libraryBook) => automatedBackupsForm.AppendText($"Decrypt Step, Completed: {libraryBook.Book}{Environment.NewLine}");
|
||||
void downloadPdfBegin(object _, LibraryBook libraryBook) => automatedBackupsForm.AppendText($"PDF Step, Begin: {libraryBook.Book}");
|
||||
// extra line after book is completely finished
|
||||
void downloadPdfCompleted(object _, LibraryBook libraryBook) => automatedBackupsForm.AppendText($"PDF Step, Completed: {libraryBook.Book}{Environment.NewLine}");
|
||||
#endregion
|
||||
|
||||
#region subscribe new form to model's events
|
||||
backupBook.DownloadBook.Begin += downloadBookBegin;
|
||||
#region subscribe new form to model's events
|
||||
backupBook.DownloadBook.Begin += downloadBookBegin;
|
||||
backupBook.DownloadBook.StatusUpdate += statusUpdate;
|
||||
backupBook.DownloadBook.Completed += downloadBookCompleted;
|
||||
backupBook.DecryptBook.Begin += decryptBookBegin;
|
||||
backupBook.DecryptBook.StatusUpdate += statusUpdate;
|
||||
backupBook.DecryptBook.Completed += decryptBookCompleted;
|
||||
backupBook.DownloadPdf.Begin += downloadPdfBegin;
|
||||
backupBook.DownloadPdf.StatusUpdate += statusUpdate;
|
||||
backupBook.DownloadPdf.Completed += downloadPdfCompleted;
|
||||
#endregion
|
||||
backupBook.DownloadPdf.Begin += downloadPdfBegin;
|
||||
backupBook.DownloadPdf.StatusUpdate += statusUpdate;
|
||||
backupBook.DownloadPdf.Completed += downloadPdfCompleted;
|
||||
#endregion
|
||||
|
||||
#region when form closes, unsubscribe from model's events
|
||||
// unsubscribe so disposed forms aren't still trying to receive notifications
|
||||
automatedBackupsForm.FormClosing += (_, __) =>
|
||||
#region when form closes, unsubscribe from model's events
|
||||
// unsubscribe so disposed forms aren't still trying to receive notifications
|
||||
automatedBackupsForm.FormClosing += (_, __) =>
|
||||
{
|
||||
backupBook.DownloadBook.Begin -= downloadBookBegin;
|
||||
backupBook.DownloadBook.StatusUpdate -= statusUpdate;
|
||||
@@ -225,48 +247,29 @@ namespace LibationWinForm.BookLiberation
|
||||
backupBook.DecryptBook.Begin -= decryptBookBegin;
|
||||
backupBook.DecryptBook.StatusUpdate -= statusUpdate;
|
||||
backupBook.DecryptBook.Completed -= decryptBookCompleted;
|
||||
backupBook.DownloadPdf.Begin -= downloadPdfBegin;
|
||||
backupBook.DownloadPdf.StatusUpdate -= statusUpdate;
|
||||
backupBook.DownloadPdf.Completed -= downloadPdfCompleted;
|
||||
};
|
||||
backupBook.DownloadPdf.Begin -= downloadPdfBegin;
|
||||
backupBook.DownloadPdf.StatusUpdate -= statusUpdate;
|
||||
backupBook.DownloadPdf.Completed -= downloadPdfCompleted;
|
||||
};
|
||||
#endregion
|
||||
|
||||
await runBackupLoop(backupBook, automatedBackupsForm);
|
||||
return automatedBackupsForm;
|
||||
}
|
||||
|
||||
// automated backups looper feels like a composible IProcessable: logic, UI, begin + process child + end
|
||||
// however the process step doesn't follow the pattern: Validate(product) + Process(product)
|
||||
private static async Task runBackupLoop(IProcessable processable, AutomatedBackupsForm automatedBackupsForm)
|
||||
private static async Task runBackupLoopAsync(IProcessable processable, AutomatedBackupsForm automatedBackupsForm)
|
||||
{
|
||||
automatedBackupsForm.Show();
|
||||
|
||||
try
|
||||
{
|
||||
do
|
||||
var shouldContinue = true;
|
||||
while (shouldContinue)
|
||||
{
|
||||
var statusHandler = await processable.ProcessFirstValidAsync();
|
||||
|
||||
if (statusHandler == null)
|
||||
{
|
||||
automatedBackupsForm.AppendText("Done. All books have been processed");
|
||||
break;
|
||||
}
|
||||
|
||||
if (statusHandler.HasErrors)
|
||||
{
|
||||
automatedBackupsForm.AppendText("ERROR. All books have not been processed. Most recent valid book: processing failed");
|
||||
foreach (var errorMessage in statusHandler.Errors)
|
||||
automatedBackupsForm.AppendText(errorMessage);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!automatedBackupsForm.KeepGoingIsChecked)
|
||||
{
|
||||
automatedBackupsForm.AppendText("'Keep going' is unchecked");
|
||||
break;
|
||||
}
|
||||
shouldContinue = validateStatus(statusHandler, automatedBackupsForm);
|
||||
}
|
||||
while (automatedBackupsForm.KeepGoingIsChecked);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -275,5 +278,48 @@ namespace LibationWinForm.BookLiberation
|
||||
|
||||
automatedBackupsForm.FinalizeUI();
|
||||
}
|
||||
|
||||
private static async Task runSingleBackupAsync(IProcessable processable, AutomatedBackupsForm automatedBackupsForm, string productId)
|
||||
{
|
||||
automatedBackupsForm.Show();
|
||||
|
||||
try
|
||||
{
|
||||
var statusHandler = await processable.ProcessSingleAsync(productId);
|
||||
validateStatus(statusHandler, automatedBackupsForm);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
automatedBackupsForm.AppendError(ex);
|
||||
}
|
||||
|
||||
automatedBackupsForm.FinalizeUI();
|
||||
}
|
||||
|
||||
private static bool validateStatus(StatusHandler statusHandler, AutomatedBackupsForm automatedBackupsForm)
|
||||
{
|
||||
if (statusHandler == null)
|
||||
{
|
||||
automatedBackupsForm.AppendText("Done. All books have been processed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (statusHandler.HasErrors)
|
||||
{
|
||||
automatedBackupsForm.AppendText("ERROR. All books have not been processed. Most recent valid book: processing failed");
|
||||
foreach (var errorMessage in statusHandler.Errors)
|
||||
automatedBackupsForm.AppendText(errorMessage);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!automatedBackupsForm.KeepGoing)
|
||||
{
|
||||
if (automatedBackupsForm.KeepGoingVisible && !automatedBackupsForm.KeepGoingChecked)
|
||||
automatedBackupsForm.AppendText("'Keep going' is unchecked");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace LibationWinForm.Dialogs
|
||||
namespace LibationWinForms.Dialogs
|
||||
{
|
||||
partial class EditQuickFilters
|
||||
{
|
||||
@@ -9,7 +9,7 @@ using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using FileManager;
|
||||
|
||||
namespace LibationWinForm.Dialogs
|
||||
namespace LibationWinForms.Dialogs
|
||||
{
|
||||
public partial class EditQuickFilters : Form
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace LibationWinForm
|
||||
namespace LibationWinForms.Dialogs
|
||||
{
|
||||
partial class EditTagsDialog
|
||||
{
|
||||
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace LibationWinForm
|
||||
namespace LibationWinForms.Dialogs
|
||||
{
|
||||
public partial class EditTagsDialog : Form
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace LibationWinForm
|
||||
namespace LibationWinForms.Dialogs
|
||||
{
|
||||
partial class IndexLibraryDialog
|
||||
{
|
||||
@@ -1,8 +1,9 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using ApplicationServices;
|
||||
using LibationWinForms.Login;
|
||||
|
||||
namespace LibationWinForm
|
||||
namespace LibationWinForms.Dialogs
|
||||
{
|
||||
public partial class IndexLibraryDialog : Form
|
||||
{
|
||||
@@ -19,12 +20,11 @@ namespace LibationWinForm
|
||||
{
|
||||
try
|
||||
{
|
||||
(TotalBooksProcessed, NewBooksAdded) = await LibraryCommands.IndexLibraryAsync(new Login.WinformResponder());
|
||||
(TotalBooksProcessed, NewBooksAdded) = await LibraryCommands.ImportLibraryAsync(new WinformResponder());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = "Error importing library. Please try again. If this happens after 2 or 3 tries, contact administrator";
|
||||
Serilog.Log.Logger.Error(ex, msg);
|
||||
var msg = "Error importing library. Please try again. If this still happens after 2 or 3 tries, stop and contact administrator";
|
||||
MessageBox.Show(msg, "Error importing library", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
|
||||
161
LibationWinForms/UNTESTED/Dialogs/LibationFilesDialog.Designer.cs
generated
Normal file
@@ -0,0 +1,161 @@
|
||||
namespace LibationWinForms.Dialogs
|
||||
{
|
||||
partial class LibationFilesDialog
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.libationFilesDescLbl = new System.Windows.Forms.Label();
|
||||
this.libationFilesCustomBtn = new System.Windows.Forms.Button();
|
||||
this.libationFilesCustomTb = new System.Windows.Forms.TextBox();
|
||||
this.libationFilesCustomRb = new System.Windows.Forms.RadioButton();
|
||||
this.libationFilesMyDocsRb = new System.Windows.Forms.RadioButton();
|
||||
this.libationFilesRootRb = new System.Windows.Forms.RadioButton();
|
||||
this.cancelBtn = new System.Windows.Forms.Button();
|
||||
this.saveBtn = new System.Windows.Forms.Button();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// libationFilesDescLbl
|
||||
//
|
||||
this.libationFilesDescLbl.AutoSize = true;
|
||||
this.libationFilesDescLbl.Location = new System.Drawing.Point(12, 9);
|
||||
this.libationFilesDescLbl.Name = "libationFilesDescLbl";
|
||||
this.libationFilesDescLbl.Size = new System.Drawing.Size(36, 13);
|
||||
this.libationFilesDescLbl.TabIndex = 0;
|
||||
this.libationFilesDescLbl.Text = "[desc]";
|
||||
//
|
||||
// libationFilesCustomBtn
|
||||
//
|
||||
this.libationFilesCustomBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.libationFilesCustomBtn.Location = new System.Drawing.Point(753, 95);
|
||||
this.libationFilesCustomBtn.Name = "libationFilesCustomBtn";
|
||||
this.libationFilesCustomBtn.Size = new System.Drawing.Size(35, 23);
|
||||
this.libationFilesCustomBtn.TabIndex = 5;
|
||||
this.libationFilesCustomBtn.Text = "...";
|
||||
this.libationFilesCustomBtn.UseVisualStyleBackColor = true;
|
||||
this.libationFilesCustomBtn.Click += new System.EventHandler(this.libationFilesCustomBtn_Click);
|
||||
//
|
||||
// libationFilesCustomTb
|
||||
//
|
||||
this.libationFilesCustomTb.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.libationFilesCustomTb.Location = new System.Drawing.Point(35, 97);
|
||||
this.libationFilesCustomTb.Name = "libationFilesCustomTb";
|
||||
this.libationFilesCustomTb.Size = new System.Drawing.Size(712, 20);
|
||||
this.libationFilesCustomTb.TabIndex = 4;
|
||||
//
|
||||
// libationFilesCustomRb
|
||||
//
|
||||
this.libationFilesCustomRb.AutoSize = true;
|
||||
this.libationFilesCustomRb.Location = new System.Drawing.Point(15, 100);
|
||||
this.libationFilesCustomRb.Name = "libationFilesCustomRb";
|
||||
this.libationFilesCustomRb.Size = new System.Drawing.Size(14, 13);
|
||||
this.libationFilesCustomRb.TabIndex = 3;
|
||||
this.libationFilesCustomRb.TabStop = true;
|
||||
this.libationFilesCustomRb.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// libationFilesMyDocsRb
|
||||
//
|
||||
this.libationFilesMyDocsRb.AutoSize = true;
|
||||
this.libationFilesMyDocsRb.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||
this.libationFilesMyDocsRb.Location = new System.Drawing.Point(15, 61);
|
||||
this.libationFilesMyDocsRb.Name = "libationFilesMyDocsRb";
|
||||
this.libationFilesMyDocsRb.Size = new System.Drawing.Size(111, 30);
|
||||
this.libationFilesMyDocsRb.TabIndex = 2;
|
||||
this.libationFilesMyDocsRb.TabStop = true;
|
||||
this.libationFilesMyDocsRb.Text = "[desc]\r\n[myDocs\\Libation]";
|
||||
this.libationFilesMyDocsRb.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// libationFilesRootRb
|
||||
//
|
||||
this.libationFilesRootRb.AutoSize = true;
|
||||
this.libationFilesRootRb.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||
this.libationFilesRootRb.Location = new System.Drawing.Point(15, 25);
|
||||
this.libationFilesRootRb.Name = "libationFilesRootRb";
|
||||
this.libationFilesRootRb.Size = new System.Drawing.Size(113, 30);
|
||||
this.libationFilesRootRb.TabIndex = 1;
|
||||
this.libationFilesRootRb.TabStop = true;
|
||||
this.libationFilesRootRb.Text = "[desc]\r\n[appDir\\Libation]";
|
||||
this.libationFilesRootRb.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// cancelBtn
|
||||
//
|
||||
this.cancelBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.cancelBtn.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||
this.cancelBtn.Location = new System.Drawing.Point(713, 124);
|
||||
this.cancelBtn.Name = "cancelBtn";
|
||||
this.cancelBtn.Size = new System.Drawing.Size(75, 23);
|
||||
this.cancelBtn.TabIndex = 10;
|
||||
this.cancelBtn.Text = "Cancel";
|
||||
this.cancelBtn.UseVisualStyleBackColor = true;
|
||||
this.cancelBtn.Click += new System.EventHandler(this.cancelBtn_Click);
|
||||
//
|
||||
// saveBtn
|
||||
//
|
||||
this.saveBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.saveBtn.Location = new System.Drawing.Point(612, 124);
|
||||
this.saveBtn.Name = "saveBtn";
|
||||
this.saveBtn.Size = new System.Drawing.Size(75, 23);
|
||||
this.saveBtn.TabIndex = 9;
|
||||
this.saveBtn.Text = "Save";
|
||||
this.saveBtn.UseVisualStyleBackColor = true;
|
||||
this.saveBtn.Click += new System.EventHandler(this.saveBtn_Click);
|
||||
//
|
||||
// LibationFilesDialog
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(800, 159);
|
||||
this.Controls.Add(this.cancelBtn);
|
||||
this.Controls.Add(this.saveBtn);
|
||||
this.Controls.Add(this.libationFilesDescLbl);
|
||||
this.Controls.Add(this.libationFilesCustomBtn);
|
||||
this.Controls.Add(this.libationFilesCustomTb);
|
||||
this.Controls.Add(this.libationFilesRootRb);
|
||||
this.Controls.Add(this.libationFilesCustomRb);
|
||||
this.Controls.Add(this.libationFilesMyDocsRb);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
|
||||
this.Name = "LibationFilesDialog";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||
this.Text = "Libation Files location";
|
||||
this.Load += new System.EventHandler(this.LibationFilesDialog_Load);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Label libationFilesDescLbl;
|
||||
private System.Windows.Forms.Button libationFilesCustomBtn;
|
||||
private System.Windows.Forms.TextBox libationFilesCustomTb;
|
||||
private System.Windows.Forms.RadioButton libationFilesCustomRb;
|
||||
private System.Windows.Forms.RadioButton libationFilesMyDocsRb;
|
||||
private System.Windows.Forms.RadioButton libationFilesRootRb;
|
||||
private System.Windows.Forms.Button cancelBtn;
|
||||
private System.Windows.Forms.Button saveBtn;
|
||||
}
|
||||
}
|
||||
67
LibationWinForms/UNTESTED/Dialogs/LibationFilesDialog.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using FileManager;
|
||||
|
||||
namespace LibationWinForms.Dialogs
|
||||
{
|
||||
public partial class LibationFilesDialog : Form
|
||||
{
|
||||
Configuration config { get; } = Configuration.Instance;
|
||||
Func<string, string> desc { get; } = Configuration.GetDescription;
|
||||
|
||||
public LibationFilesDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
this.libationFilesCustomTb.TextChanged += (_, __) =>
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(libationFilesCustomTb.Text))
|
||||
this.libationFilesCustomRb.Checked = true;
|
||||
};
|
||||
}
|
||||
|
||||
private void LibationFilesDialog_Load(object sender, EventArgs e)
|
||||
{
|
||||
libationFilesDescLbl.Text = desc(nameof(config.LibationFiles));
|
||||
this.libationFilesRootRb.Text = "In the same folder that Libation is running from\r\n" + Configuration.AppDir;
|
||||
this.libationFilesMyDocsRb.Text = "In My Documents\r\n" + Configuration.MyDocs;
|
||||
if (config.LibationFiles == Configuration.AppDir)
|
||||
libationFilesRootRb.Checked = true;
|
||||
else if (config.LibationFiles == Configuration.MyDocs)
|
||||
libationFilesMyDocsRb.Checked = true;
|
||||
else
|
||||
{
|
||||
libationFilesCustomRb.Checked = true;
|
||||
libationFilesCustomTb.Text = config.LibationFiles;
|
||||
}
|
||||
}
|
||||
|
||||
private void libationFilesCustomBtn_Click(object sender, EventArgs e) => selectFolder("Search for Libation Files location", this.libationFilesCustomTb);
|
||||
|
||||
private static void selectFolder(string desc, TextBox textbox)
|
||||
{
|
||||
using var dialog = new FolderBrowserDialog { Description = desc, SelectedPath = "" };
|
||||
dialog.ShowDialog();
|
||||
if (!string.IsNullOrWhiteSpace(dialog.SelectedPath))
|
||||
textbox.Text = dialog.SelectedPath;
|
||||
}
|
||||
|
||||
private void saveBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
var libationDir
|
||||
= libationFilesRootRb.Checked ? Configuration.AppDir
|
||||
: libationFilesMyDocsRb.Checked ? Configuration.MyDocs
|
||||
: libationFilesCustomTb.Text;
|
||||
if (!config.TrySetLibationFiles(libationDir))
|
||||
{
|
||||
MessageBox.Show("Not saving change to Libation Files location. This folder does not exist:\r\n" + libationDir);
|
||||
return;
|
||||
}
|
||||
|
||||
this.DialogResult = DialogResult.OK;
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private void cancelBtn_Click(object sender, EventArgs e) => this.Close();
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace LibationWinForm.Dialogs.Login
|
||||
namespace LibationWinForms.Dialogs.Login
|
||||
{
|
||||
partial class AudibleLoginDialog
|
||||
{
|
||||
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace LibationWinForm.Dialogs.Login
|
||||
namespace LibationWinForms.Dialogs.Login
|
||||
{
|
||||
public partial class AudibleLoginDialog : Form
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace LibationWinForm.Dialogs.Login
|
||||
namespace LibationWinForms.Dialogs.Login
|
||||
{
|
||||
partial class CaptchaDialog
|
||||
{
|
||||
@@ -3,7 +3,7 @@ using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace LibationWinForm.Dialogs.Login
|
||||
namespace LibationWinForms.Dialogs.Login
|
||||
{
|
||||
public partial class CaptchaDialog : Form
|
||||
{
|
||||
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using LibationWinForm.Dialogs.Login;
|
||||
using LibationWinForms.Dialogs.Login;
|
||||
|
||||
namespace LibationWinForm.Login
|
||||
namespace LibationWinForms.Login
|
||||
{
|
||||
public class WinformResponder : AudibleApi.ILoginCallback
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace LibationWinForm.Dialogs.Login
|
||||
namespace LibationWinForms.Dialogs.Login
|
||||
{
|
||||
partial class _2faCodeDialog
|
||||
{
|
||||
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace LibationWinForm.Dialogs.Login
|
||||
namespace LibationWinForms.Dialogs.Login
|
||||
{
|
||||
public partial class _2faCodeDialog : Form
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace LibationWinForm.Dialogs
|
||||
namespace LibationWinForms.Dialogs
|
||||
{
|
||||
partial class SearchSyntaxDialog
|
||||
{
|
||||
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace LibationWinForm.Dialogs
|
||||
namespace LibationWinForms.Dialogs
|
||||
{
|
||||
public partial class SearchSyntaxDialog : Form
|
||||
{
|
||||
321
LibationWinForms/UNTESTED/Dialogs/SettingsDialog.Designer.cs
generated
Normal file
@@ -0,0 +1,321 @@
|
||||
namespace LibationWinForms.Dialogs
|
||||
{
|
||||
partial class SettingsDialog
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.decryptKeyLbl = new System.Windows.Forms.Label();
|
||||
this.decryptKeyTb = new System.Windows.Forms.TextBox();
|
||||
this.booksLocationLbl = new System.Windows.Forms.Label();
|
||||
this.booksLocationTb = new System.Windows.Forms.TextBox();
|
||||
this.booksLocationSearchBtn = new System.Windows.Forms.Button();
|
||||
this.decryptKeyDescLbl = new System.Windows.Forms.Label();
|
||||
this.booksLocationDescLbl = new System.Windows.Forms.Label();
|
||||
this.downloadsInProgressGb = new System.Windows.Forms.GroupBox();
|
||||
this.downloadsInProgressLibationFilesRb = new System.Windows.Forms.RadioButton();
|
||||
this.downloadsInProgressWinTempRb = new System.Windows.Forms.RadioButton();
|
||||
this.downloadsInProgressDescLbl = new System.Windows.Forms.Label();
|
||||
this.decryptInProgressGb = new System.Windows.Forms.GroupBox();
|
||||
this.decryptInProgressLibationFilesRb = new System.Windows.Forms.RadioButton();
|
||||
this.decryptInProgressWinTempRb = new System.Windows.Forms.RadioButton();
|
||||
this.decryptInProgressDescLbl = new System.Windows.Forms.Label();
|
||||
this.saveBtn = new System.Windows.Forms.Button();
|
||||
this.cancelBtn = new System.Windows.Forms.Button();
|
||||
this.audibleLocaleLbl = new System.Windows.Forms.Label();
|
||||
this.audibleLocaleCb = new System.Windows.Forms.ComboBox();
|
||||
this.groupBox1 = new System.Windows.Forms.GroupBox();
|
||||
this.downloadsInProgressGb.SuspendLayout();
|
||||
this.decryptInProgressGb.SuspendLayout();
|
||||
this.groupBox1.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// decryptKeyLbl
|
||||
//
|
||||
this.decryptKeyLbl.AutoSize = true;
|
||||
this.decryptKeyLbl.Location = new System.Drawing.Point(6, 22);
|
||||
this.decryptKeyLbl.Name = "decryptKeyLbl";
|
||||
this.decryptKeyLbl.Size = new System.Drawing.Size(64, 13);
|
||||
this.decryptKeyLbl.TabIndex = 0;
|
||||
this.decryptKeyLbl.Text = "Decrypt key";
|
||||
//
|
||||
// decryptKeyTb
|
||||
//
|
||||
this.decryptKeyTb.Location = new System.Drawing.Point(76, 19);
|
||||
this.decryptKeyTb.Name = "decryptKeyTb";
|
||||
this.decryptKeyTb.Size = new System.Drawing.Size(100, 20);
|
||||
this.decryptKeyTb.TabIndex = 1;
|
||||
//
|
||||
// booksLocationLbl
|
||||
//
|
||||
this.booksLocationLbl.AutoSize = true;
|
||||
this.booksLocationLbl.Location = new System.Drawing.Point(12, 17);
|
||||
this.booksLocationLbl.Name = "booksLocationLbl";
|
||||
this.booksLocationLbl.Size = new System.Drawing.Size(77, 13);
|
||||
this.booksLocationLbl.TabIndex = 0;
|
||||
this.booksLocationLbl.Text = "Books location";
|
||||
//
|
||||
// booksLocationTb
|
||||
//
|
||||
this.booksLocationTb.Location = new System.Drawing.Point(95, 14);
|
||||
this.booksLocationTb.Name = "booksLocationTb";
|
||||
this.booksLocationTb.Size = new System.Drawing.Size(652, 20);
|
||||
this.booksLocationTb.TabIndex = 1;
|
||||
//
|
||||
// booksLocationSearchBtn
|
||||
//
|
||||
this.booksLocationSearchBtn.Location = new System.Drawing.Point(753, 12);
|
||||
this.booksLocationSearchBtn.Name = "booksLocationSearchBtn";
|
||||
this.booksLocationSearchBtn.Size = new System.Drawing.Size(35, 23);
|
||||
this.booksLocationSearchBtn.TabIndex = 2;
|
||||
this.booksLocationSearchBtn.Text = "...";
|
||||
this.booksLocationSearchBtn.UseVisualStyleBackColor = true;
|
||||
this.booksLocationSearchBtn.Click += new System.EventHandler(this.booksLocationSearchBtn_Click);
|
||||
//
|
||||
// decryptKeyDescLbl
|
||||
//
|
||||
this.decryptKeyDescLbl.AutoSize = true;
|
||||
this.decryptKeyDescLbl.Location = new System.Drawing.Point(73, 42);
|
||||
this.decryptKeyDescLbl.Name = "decryptKeyDescLbl";
|
||||
this.decryptKeyDescLbl.Size = new System.Drawing.Size(36, 13);
|
||||
this.decryptKeyDescLbl.TabIndex = 2;
|
||||
this.decryptKeyDescLbl.Text = "[desc]";
|
||||
//
|
||||
// booksLocationDescLbl
|
||||
//
|
||||
this.booksLocationDescLbl.AutoSize = true;
|
||||
this.booksLocationDescLbl.Location = new System.Drawing.Point(92, 37);
|
||||
this.booksLocationDescLbl.Name = "booksLocationDescLbl";
|
||||
this.booksLocationDescLbl.Size = new System.Drawing.Size(36, 13);
|
||||
this.booksLocationDescLbl.TabIndex = 3;
|
||||
this.booksLocationDescLbl.Text = "[desc]";
|
||||
//
|
||||
// downloadsInProgressGb
|
||||
//
|
||||
this.downloadsInProgressGb.Controls.Add(this.downloadsInProgressLibationFilesRb);
|
||||
this.downloadsInProgressGb.Controls.Add(this.downloadsInProgressWinTempRb);
|
||||
this.downloadsInProgressGb.Controls.Add(this.downloadsInProgressDescLbl);
|
||||
this.downloadsInProgressGb.Location = new System.Drawing.Point(15, 58);
|
||||
this.downloadsInProgressGb.Name = "downloadsInProgressGb";
|
||||
this.downloadsInProgressGb.Size = new System.Drawing.Size(758, 117);
|
||||
this.downloadsInProgressGb.TabIndex = 4;
|
||||
this.downloadsInProgressGb.TabStop = false;
|
||||
this.downloadsInProgressGb.Text = "Downloads in progress";
|
||||
//
|
||||
// downloadsInProgressLibationFilesRb
|
||||
//
|
||||
this.downloadsInProgressLibationFilesRb.AutoSize = true;
|
||||
this.downloadsInProgressLibationFilesRb.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||
this.downloadsInProgressLibationFilesRb.Location = new System.Drawing.Point(9, 81);
|
||||
this.downloadsInProgressLibationFilesRb.Name = "downloadsInProgressLibationFilesRb";
|
||||
this.downloadsInProgressLibationFilesRb.Size = new System.Drawing.Size(193, 30);
|
||||
this.downloadsInProgressLibationFilesRb.TabIndex = 2;
|
||||
this.downloadsInProgressLibationFilesRb.TabStop = true;
|
||||
this.downloadsInProgressLibationFilesRb.Text = "[desc]\r\n[libationFiles\\DownloadsInProgress]";
|
||||
this.downloadsInProgressLibationFilesRb.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// downloadsInProgressWinTempRb
|
||||
//
|
||||
this.downloadsInProgressWinTempRb.AutoSize = true;
|
||||
this.downloadsInProgressWinTempRb.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||
this.downloadsInProgressWinTempRb.Location = new System.Drawing.Point(9, 45);
|
||||
this.downloadsInProgressWinTempRb.Name = "downloadsInProgressWinTempRb";
|
||||
this.downloadsInProgressWinTempRb.Size = new System.Drawing.Size(182, 30);
|
||||
this.downloadsInProgressWinTempRb.TabIndex = 1;
|
||||
this.downloadsInProgressWinTempRb.TabStop = true;
|
||||
this.downloadsInProgressWinTempRb.Text = "[desc]\r\n[winTemp\\DownloadsInProgress]";
|
||||
this.downloadsInProgressWinTempRb.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// downloadsInProgressDescLbl
|
||||
//
|
||||
this.downloadsInProgressDescLbl.AutoSize = true;
|
||||
this.downloadsInProgressDescLbl.Location = new System.Drawing.Point(6, 16);
|
||||
this.downloadsInProgressDescLbl.Name = "downloadsInProgressDescLbl";
|
||||
this.downloadsInProgressDescLbl.Size = new System.Drawing.Size(38, 26);
|
||||
this.downloadsInProgressDescLbl.TabIndex = 0;
|
||||
this.downloadsInProgressDescLbl.Text = "[desc]\r\n[line 2]";
|
||||
//
|
||||
// decryptInProgressGb
|
||||
//
|
||||
this.decryptInProgressGb.Controls.Add(this.decryptInProgressLibationFilesRb);
|
||||
this.decryptInProgressGb.Controls.Add(this.decryptInProgressWinTempRb);
|
||||
this.decryptInProgressGb.Controls.Add(this.decryptInProgressDescLbl);
|
||||
this.decryptInProgressGb.Location = new System.Drawing.Point(9, 183);
|
||||
this.decryptInProgressGb.Name = "decryptInProgressGb";
|
||||
this.decryptInProgressGb.Size = new System.Drawing.Size(758, 117);
|
||||
this.decryptInProgressGb.TabIndex = 5;
|
||||
this.decryptInProgressGb.TabStop = false;
|
||||
this.decryptInProgressGb.Text = "Decrypt in progress";
|
||||
//
|
||||
// decryptInProgressLibationFilesRb
|
||||
//
|
||||
this.decryptInProgressLibationFilesRb.AutoSize = true;
|
||||
this.decryptInProgressLibationFilesRb.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||
this.decryptInProgressLibationFilesRb.Location = new System.Drawing.Point(6, 81);
|
||||
this.decryptInProgressLibationFilesRb.Name = "decryptInProgressLibationFilesRb";
|
||||
this.decryptInProgressLibationFilesRb.Size = new System.Drawing.Size(177, 30);
|
||||
this.decryptInProgressLibationFilesRb.TabIndex = 2;
|
||||
this.decryptInProgressLibationFilesRb.TabStop = true;
|
||||
this.decryptInProgressLibationFilesRb.Text = "[desc]\r\n[libationFiles\\DecryptInProgress]";
|
||||
this.decryptInProgressLibationFilesRb.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// decryptInProgressWinTempRb
|
||||
//
|
||||
this.decryptInProgressWinTempRb.AutoSize = true;
|
||||
this.decryptInProgressWinTempRb.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||
this.decryptInProgressWinTempRb.Location = new System.Drawing.Point(6, 45);
|
||||
this.decryptInProgressWinTempRb.Name = "decryptInProgressWinTempRb";
|
||||
this.decryptInProgressWinTempRb.Size = new System.Drawing.Size(166, 30);
|
||||
this.decryptInProgressWinTempRb.TabIndex = 1;
|
||||
this.decryptInProgressWinTempRb.TabStop = true;
|
||||
this.decryptInProgressWinTempRb.Text = "[desc]\r\n[winTemp\\DecryptInProgress]";
|
||||
this.decryptInProgressWinTempRb.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// decryptInProgressDescLbl
|
||||
//
|
||||
this.decryptInProgressDescLbl.AutoSize = true;
|
||||
this.decryptInProgressDescLbl.Location = new System.Drawing.Point(6, 16);
|
||||
this.decryptInProgressDescLbl.Name = "decryptInProgressDescLbl";
|
||||
this.decryptInProgressDescLbl.Size = new System.Drawing.Size(38, 26);
|
||||
this.decryptInProgressDescLbl.TabIndex = 0;
|
||||
this.decryptInProgressDescLbl.Text = "[desc]\r\n[line 2]";
|
||||
//
|
||||
// saveBtn
|
||||
//
|
||||
this.saveBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.saveBtn.Location = new System.Drawing.Point(612, 404);
|
||||
this.saveBtn.Name = "saveBtn";
|
||||
this.saveBtn.Size = new System.Drawing.Size(75, 23);
|
||||
this.saveBtn.TabIndex = 7;
|
||||
this.saveBtn.Text = "Save";
|
||||
this.saveBtn.UseVisualStyleBackColor = true;
|
||||
this.saveBtn.Click += new System.EventHandler(this.saveBtn_Click);
|
||||
//
|
||||
// cancelBtn
|
||||
//
|
||||
this.cancelBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.cancelBtn.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||
this.cancelBtn.Location = new System.Drawing.Point(713, 404);
|
||||
this.cancelBtn.Name = "cancelBtn";
|
||||
this.cancelBtn.Size = new System.Drawing.Size(75, 23);
|
||||
this.cancelBtn.TabIndex = 8;
|
||||
this.cancelBtn.Text = "Cancel";
|
||||
this.cancelBtn.UseVisualStyleBackColor = true;
|
||||
this.cancelBtn.Click += new System.EventHandler(this.cancelBtn_Click);
|
||||
//
|
||||
// audibleLocaleLbl
|
||||
//
|
||||
this.audibleLocaleLbl.AutoSize = true;
|
||||
this.audibleLocaleLbl.Location = new System.Drawing.Point(12, 56);
|
||||
this.audibleLocaleLbl.Name = "audibleLocaleLbl";
|
||||
this.audibleLocaleLbl.Size = new System.Drawing.Size(77, 13);
|
||||
this.audibleLocaleLbl.TabIndex = 4;
|
||||
this.audibleLocaleLbl.Text = "Audible Locale";
|
||||
//
|
||||
// audibleLocaleCb
|
||||
//
|
||||
this.audibleLocaleCb.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.audibleLocaleCb.FormattingEnabled = true;
|
||||
this.audibleLocaleCb.Items.AddRange(new object[] {
|
||||
"us",
|
||||
"uk",
|
||||
"germany",
|
||||
"france",
|
||||
"canada"});
|
||||
this.audibleLocaleCb.Location = new System.Drawing.Point(95, 53);
|
||||
this.audibleLocaleCb.Name = "audibleLocaleCb";
|
||||
this.audibleLocaleCb.Size = new System.Drawing.Size(53, 21);
|
||||
this.audibleLocaleCb.TabIndex = 5;
|
||||
//
|
||||
// groupBox1
|
||||
//
|
||||
this.groupBox1.Controls.Add(this.decryptKeyTb);
|
||||
this.groupBox1.Controls.Add(this.decryptKeyLbl);
|
||||
this.groupBox1.Controls.Add(this.decryptKeyDescLbl);
|
||||
this.groupBox1.Controls.Add(this.downloadsInProgressGb);
|
||||
this.groupBox1.Controls.Add(this.decryptInProgressGb);
|
||||
this.groupBox1.Location = new System.Drawing.Point(15, 90);
|
||||
this.groupBox1.Name = "groupBox1";
|
||||
this.groupBox1.Size = new System.Drawing.Size(773, 308);
|
||||
this.groupBox1.TabIndex = 6;
|
||||
this.groupBox1.TabStop = false;
|
||||
this.groupBox1.Text = "Advanced settings for control freaks";
|
||||
//
|
||||
// SettingsDialog
|
||||
//
|
||||
this.AcceptButton = this.saveBtn;
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.CancelButton = this.cancelBtn;
|
||||
this.ClientSize = new System.Drawing.Size(800, 439);
|
||||
this.Controls.Add(this.groupBox1);
|
||||
this.Controls.Add(this.audibleLocaleCb);
|
||||
this.Controls.Add(this.audibleLocaleLbl);
|
||||
this.Controls.Add(this.cancelBtn);
|
||||
this.Controls.Add(this.saveBtn);
|
||||
this.Controls.Add(this.booksLocationDescLbl);
|
||||
this.Controls.Add(this.booksLocationSearchBtn);
|
||||
this.Controls.Add(this.booksLocationTb);
|
||||
this.Controls.Add(this.booksLocationLbl);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
|
||||
this.Name = "SettingsDialog";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||
this.Text = "Edit Settings";
|
||||
this.Load += new System.EventHandler(this.SettingsDialog_Load);
|
||||
this.downloadsInProgressGb.ResumeLayout(false);
|
||||
this.downloadsInProgressGb.PerformLayout();
|
||||
this.decryptInProgressGb.ResumeLayout(false);
|
||||
this.decryptInProgressGb.PerformLayout();
|
||||
this.groupBox1.ResumeLayout(false);
|
||||
this.groupBox1.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
private System.Windows.Forms.Label decryptKeyLbl;
|
||||
private System.Windows.Forms.TextBox decryptKeyTb;
|
||||
private System.Windows.Forms.Label booksLocationLbl;
|
||||
private System.Windows.Forms.TextBox booksLocationTb;
|
||||
private System.Windows.Forms.Button booksLocationSearchBtn;
|
||||
private System.Windows.Forms.Label decryptKeyDescLbl;
|
||||
private System.Windows.Forms.Label booksLocationDescLbl;
|
||||
private System.Windows.Forms.GroupBox downloadsInProgressGb;
|
||||
private System.Windows.Forms.Label downloadsInProgressDescLbl;
|
||||
private System.Windows.Forms.RadioButton downloadsInProgressWinTempRb;
|
||||
private System.Windows.Forms.RadioButton downloadsInProgressLibationFilesRb;
|
||||
private System.Windows.Forms.GroupBox decryptInProgressGb;
|
||||
private System.Windows.Forms.Label decryptInProgressDescLbl;
|
||||
private System.Windows.Forms.RadioButton decryptInProgressLibationFilesRb;
|
||||
private System.Windows.Forms.RadioButton decryptInProgressWinTempRb;
|
||||
private System.Windows.Forms.Button saveBtn;
|
||||
private System.Windows.Forms.Button cancelBtn;
|
||||
private System.Windows.Forms.Label audibleLocaleLbl;
|
||||
private System.Windows.Forms.ComboBox audibleLocaleCb;
|
||||
private System.Windows.Forms.GroupBox groupBox1;
|
||||
}
|
||||
}
|
||||
100
LibationWinForms/UNTESTED/Dialogs/SettingsDialog.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
using Dinah.Core;
|
||||
using FileManager;
|
||||
|
||||
namespace LibationWinForms.Dialogs
|
||||
{
|
||||
public partial class SettingsDialog : Form
|
||||
{
|
||||
Configuration config { get; } = Configuration.Instance;
|
||||
Func<string, string> desc { get; } = Configuration.GetDescription;
|
||||
|
||||
public SettingsDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void SettingsDialog_Load(object sender, EventArgs e)
|
||||
{
|
||||
this.decryptKeyTb.Text = config.DecryptKey;
|
||||
this.decryptKeyDescLbl.Text = desc(nameof(config.DecryptKey));
|
||||
this.booksLocationDescLbl.Text = desc(nameof(config.Books));
|
||||
this.downloadsInProgressDescLbl.Text = desc(nameof(config.DownloadsInProgressEnum));
|
||||
this.decryptInProgressDescLbl.Text = desc(nameof(config.DecryptInProgressEnum));
|
||||
|
||||
var winTempText = "In your Windows temporary folder\r\n";
|
||||
this.downloadsInProgressWinTempRb.Text = $"{winTempText}{Path.Combine(Configuration.WinTemp, "DownloadsInProgress")}";
|
||||
this.decryptInProgressWinTempRb.Text = $"{winTempText}{Path.Combine(Configuration.WinTemp, "DecryptInProgress")}";
|
||||
|
||||
var libFileText = "In your Libation Files (ie: program-created files)\r\n";
|
||||
this.downloadsInProgressLibationFilesRb.Text = $"{libFileText}{Path.Combine(config.LibationFiles, "DownloadsInProgress")}";
|
||||
this.decryptInProgressLibationFilesRb.Text = $"{libFileText}{Path.Combine(config.LibationFiles, "DecryptInProgress")}";
|
||||
|
||||
this.booksLocationTb.Text
|
||||
= !string.IsNullOrWhiteSpace(config.Books)
|
||||
? config.Books
|
||||
: Path.GetDirectoryName(Exe.FileLocationOnDisk);
|
||||
|
||||
this.audibleLocaleCb.Text
|
||||
= !string.IsNullOrWhiteSpace(config.LocaleCountryCode)
|
||||
? config.LocaleCountryCode
|
||||
: "us";
|
||||
|
||||
switch (config.DownloadsInProgressEnum)
|
||||
{
|
||||
case "LibationFiles":
|
||||
downloadsInProgressLibationFilesRb.Checked = true;
|
||||
break;
|
||||
case "WinTemp":
|
||||
default:
|
||||
downloadsInProgressWinTempRb.Checked = true;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (config.DecryptInProgressEnum)
|
||||
{
|
||||
case "LibationFiles":
|
||||
decryptInProgressLibationFilesRb.Checked = true;
|
||||
break;
|
||||
case "WinTemp":
|
||||
default:
|
||||
decryptInProgressWinTempRb.Checked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void booksLocationSearchBtn_Click(object sender, EventArgs e) => selectFolder("Search for books location", this.booksLocationTb);
|
||||
|
||||
private static void selectFolder(string desc, TextBox textbox)
|
||||
{
|
||||
using var dialog = new FolderBrowserDialog { Description = desc, SelectedPath = "" };
|
||||
dialog.ShowDialog();
|
||||
if (!string.IsNullOrWhiteSpace(dialog.SelectedPath))
|
||||
textbox.Text = dialog.SelectedPath;
|
||||
}
|
||||
|
||||
private void saveBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
config.DecryptKey = this.decryptKeyTb.Text;
|
||||
config.LocaleCountryCode = this.audibleLocaleCb.Text;
|
||||
config.DownloadsInProgressEnum = downloadsInProgressLibationFilesRb.Checked ? "LibationFiles" : "WinTemp";
|
||||
config.DecryptInProgressEnum = decryptInProgressLibationFilesRb.Checked ? "LibationFiles" : "WinTemp";
|
||||
|
||||
var newBooks = this.booksLocationTb.Text;
|
||||
if (!Directory.Exists(newBooks))
|
||||
{
|
||||
MessageBox.Show($"Not saving change to Books location. This folder does not exist:\r\n{newBooks}");
|
||||
return;
|
||||
}
|
||||
else
|
||||
config.Books = newBooks;
|
||||
|
||||
this.DialogResult = DialogResult.OK;
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private void cancelBtn_Click(object sender, EventArgs e) => this.Close();
|
||||
}
|
||||
}
|
||||
120
LibationWinForms/UNTESTED/Dialogs/SettingsDialog.resx
Normal file
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
99
LibationWinForms/UNTESTED/Dialogs/SetupDialog.Designer.cs
generated
Normal file
@@ -0,0 +1,99 @@
|
||||
namespace LibationWinForms.Dialogs
|
||||
{
|
||||
partial class SetupDialog
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SetupDialog));
|
||||
this.welcomeLbl = new System.Windows.Forms.Label();
|
||||
this.noQuestionsBtn = new System.Windows.Forms.Button();
|
||||
this.basicBtn = new System.Windows.Forms.Button();
|
||||
this.advancedBtn = new System.Windows.Forms.Button();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// welcomeLbl
|
||||
//
|
||||
this.welcomeLbl.AutoSize = true;
|
||||
this.welcomeLbl.Location = new System.Drawing.Point(12, 9);
|
||||
this.welcomeLbl.Name = "welcomeLbl";
|
||||
this.welcomeLbl.Size = new System.Drawing.Size(399, 78);
|
||||
this.welcomeLbl.TabIndex = 0;
|
||||
this.welcomeLbl.Text = resources.GetString("welcomeLbl.Text");
|
||||
//
|
||||
// noQuestionsBtn
|
||||
//
|
||||
this.noQuestionsBtn.Location = new System.Drawing.Point(15, 90);
|
||||
this.noQuestionsBtn.Name = "noQuestionsBtn";
|
||||
this.noQuestionsBtn.Size = new System.Drawing.Size(396, 57);
|
||||
this.noQuestionsBtn.TabIndex = 1;
|
||||
this.noQuestionsBtn.Text = "NO-QUESTIONS SETUP\r\n\r\nAccept all defaults";
|
||||
this.noQuestionsBtn.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// basicBtn
|
||||
//
|
||||
this.basicBtn.Location = new System.Drawing.Point(15, 153);
|
||||
this.basicBtn.Name = "basicBtn";
|
||||
this.basicBtn.Size = new System.Drawing.Size(396, 57);
|
||||
this.basicBtn.TabIndex = 2;
|
||||
this.basicBtn.Text = "BASIC SETUP\r\n\r\nChoose settings";
|
||||
this.basicBtn.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// advancedBtn
|
||||
//
|
||||
this.advancedBtn.Location = new System.Drawing.Point(15, 216);
|
||||
this.advancedBtn.Name = "advancedBtn";
|
||||
this.advancedBtn.Size = new System.Drawing.Size(396, 57);
|
||||
this.advancedBtn.TabIndex = 3;
|
||||
this.advancedBtn.Text = "ADVANCED SETUP\r\n\r\nChoose settings and where to store them";
|
||||
this.advancedBtn.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// SetupDialog
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(423, 285);
|
||||
this.Controls.Add(this.advancedBtn);
|
||||
this.Controls.Add(this.basicBtn);
|
||||
this.Controls.Add(this.noQuestionsBtn);
|
||||
this.Controls.Add(this.welcomeLbl);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
|
||||
this.Name = "SetupDialog";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "Welcome to Libation";
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Label welcomeLbl;
|
||||
private System.Windows.Forms.Button noQuestionsBtn;
|
||||
private System.Windows.Forms.Button basicBtn;
|
||||
private System.Windows.Forms.Button advancedBtn;
|
||||
}
|
||||
}
|
||||
37
LibationWinForms/UNTESTED/Dialogs/SetupDialog.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace LibationWinForms.Dialogs
|
||||
{
|
||||
public partial class SetupDialog : Form
|
||||
{
|
||||
public event EventHandler NoQuestionsBtn_Click
|
||||
{
|
||||
add => noQuestionsBtn.Click += value;
|
||||
remove => noQuestionsBtn.Click -= value;
|
||||
}
|
||||
|
||||
public event EventHandler BasicBtn_Click
|
||||
{
|
||||
add => basicBtn.Click += value;
|
||||
remove => basicBtn.Click -= value;
|
||||
}
|
||||
|
||||
public event EventHandler AdvancedBtn_Click
|
||||
{
|
||||
add => advancedBtn.Click += value;
|
||||
remove => advancedBtn.Click -= value;
|
||||
}
|
||||
|
||||
public SetupDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
noQuestionsBtn.Click += btn_Click;
|
||||
basicBtn.Click += btn_Click;
|
||||
advancedBtn.Click += btn_Click;
|
||||
}
|
||||
|
||||
private void btn_Click(object sender, EventArgs e) => Close();
|
||||
}
|
||||
}
|
||||
128
LibationWinForms/UNTESTED/Dialogs/SetupDialog.resx
Normal file
@@ -0,0 +1,128 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="welcomeLbl.Text" xml:space="preserve">
|
||||
<value>This appears to be your first time using Libation or a previous setup was incomplete.
|
||||
|
||||
Please fill in a few settings. You can also change these settings later.
|
||||
|
||||
After you make your selections, get started by importing your library.
|
||||
Go to Import > Scan Library</value>
|
||||
</data>
|
||||
</root>
|
||||
302
LibationWinForms/UNTESTED/Form1.Designer.cs
generated
Normal file
@@ -0,0 +1,302 @@
|
||||
namespace LibationWinForms
|
||||
{
|
||||
partial class Form1
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
|
||||
this.gridPanel = new System.Windows.Forms.Panel();
|
||||
this.filterHelpBtn = new System.Windows.Forms.Button();
|
||||
this.filterBtn = new System.Windows.Forms.Button();
|
||||
this.filterSearchTb = new System.Windows.Forms.TextBox();
|
||||
this.menuStrip1 = new System.Windows.Forms.MenuStrip();
|
||||
this.importToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.scanLibraryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.liberateToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.beginBookBackupsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.beginPdfBackupsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.quickFiltersToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.firstFilterIsDefaultToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.editQuickFiltersToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.settingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.basicSettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.advancedSettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
|
||||
this.visibleCountLbl = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.springLbl = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.backupsCountsLbl = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.pdfsCountsLbl = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.addFilterBtn = new System.Windows.Forms.Button();
|
||||
this.menuStrip1.SuspendLayout();
|
||||
this.statusStrip1.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// gridPanel
|
||||
//
|
||||
this.gridPanel.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.gridPanel.Location = new System.Drawing.Point(12, 56);
|
||||
this.gridPanel.Name = "gridPanel";
|
||||
this.gridPanel.Size = new System.Drawing.Size(839, 386);
|
||||
this.gridPanel.TabIndex = 5;
|
||||
//
|
||||
// filterHelpBtn
|
||||
//
|
||||
this.filterHelpBtn.Location = new System.Drawing.Point(12, 27);
|
||||
this.filterHelpBtn.Name = "filterHelpBtn";
|
||||
this.filterHelpBtn.Size = new System.Drawing.Size(22, 23);
|
||||
this.filterHelpBtn.TabIndex = 3;
|
||||
this.filterHelpBtn.Text = "?";
|
||||
this.filterHelpBtn.UseVisualStyleBackColor = true;
|
||||
this.filterHelpBtn.Click += new System.EventHandler(this.filterHelpBtn_Click);
|
||||
//
|
||||
// filterBtn
|
||||
//
|
||||
this.filterBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.filterBtn.Location = new System.Drawing.Point(776, 27);
|
||||
this.filterBtn.Name = "filterBtn";
|
||||
this.filterBtn.Size = new System.Drawing.Size(75, 23);
|
||||
this.filterBtn.TabIndex = 2;
|
||||
this.filterBtn.Text = "Filter";
|
||||
this.filterBtn.UseVisualStyleBackColor = true;
|
||||
this.filterBtn.Click += new System.EventHandler(this.filterBtn_Click);
|
||||
//
|
||||
// filterSearchTb
|
||||
//
|
||||
this.filterSearchTb.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.filterSearchTb.Location = new System.Drawing.Point(186, 29);
|
||||
this.filterSearchTb.Name = "filterSearchTb";
|
||||
this.filterSearchTb.Size = new System.Drawing.Size(584, 20);
|
||||
this.filterSearchTb.TabIndex = 1;
|
||||
this.filterSearchTb.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.filterSearchTb_KeyPress);
|
||||
//
|
||||
// menuStrip1
|
||||
//
|
||||
this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.importToolStripMenuItem,
|
||||
this.liberateToolStripMenuItem,
|
||||
this.quickFiltersToolStripMenuItem,
|
||||
this.settingsToolStripMenuItem});
|
||||
this.menuStrip1.Location = new System.Drawing.Point(0, 0);
|
||||
this.menuStrip1.Name = "menuStrip1";
|
||||
this.menuStrip1.Size = new System.Drawing.Size(863, 24);
|
||||
this.menuStrip1.TabIndex = 0;
|
||||
this.menuStrip1.Text = "menuStrip1";
|
||||
//
|
||||
// importToolStripMenuItem
|
||||
//
|
||||
this.importToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.scanLibraryToolStripMenuItem});
|
||||
this.importToolStripMenuItem.Name = "importToolStripMenuItem";
|
||||
this.importToolStripMenuItem.Size = new System.Drawing.Size(55, 20);
|
||||
this.importToolStripMenuItem.Text = "&Import";
|
||||
//
|
||||
// scanLibraryToolStripMenuItem
|
||||
//
|
||||
this.scanLibraryToolStripMenuItem.Name = "scanLibraryToolStripMenuItem";
|
||||
this.scanLibraryToolStripMenuItem.Size = new System.Drawing.Size(138, 22);
|
||||
this.scanLibraryToolStripMenuItem.Text = "Scan &Library";
|
||||
this.scanLibraryToolStripMenuItem.Click += new System.EventHandler(this.scanLibraryToolStripMenuItem_Click);
|
||||
//
|
||||
// liberateToolStripMenuItem
|
||||
//
|
||||
this.liberateToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.beginBookBackupsToolStripMenuItem,
|
||||
this.beginPdfBackupsToolStripMenuItem});
|
||||
this.liberateToolStripMenuItem.Name = "liberateToolStripMenuItem";
|
||||
this.liberateToolStripMenuItem.Size = new System.Drawing.Size(61, 20);
|
||||
this.liberateToolStripMenuItem.Text = "&Liberate";
|
||||
//
|
||||
// beginBookBackupsToolStripMenuItem
|
||||
//
|
||||
this.beginBookBackupsToolStripMenuItem.Name = "beginBookBackupsToolStripMenuItem";
|
||||
this.beginBookBackupsToolStripMenuItem.Size = new System.Drawing.Size(248, 22);
|
||||
this.beginBookBackupsToolStripMenuItem.Text = "Begin &Book and PDF Backups: {0}";
|
||||
this.beginBookBackupsToolStripMenuItem.Click += new System.EventHandler(this.beginBookBackupsToolStripMenuItem_Click);
|
||||
//
|
||||
// beginPdfBackupsToolStripMenuItem
|
||||
//
|
||||
this.beginPdfBackupsToolStripMenuItem.Name = "beginPdfBackupsToolStripMenuItem";
|
||||
this.beginPdfBackupsToolStripMenuItem.Size = new System.Drawing.Size(248, 22);
|
||||
this.beginPdfBackupsToolStripMenuItem.Text = "Begin &PDF Only Backups: {0}";
|
||||
this.beginPdfBackupsToolStripMenuItem.Click += new System.EventHandler(this.beginPdfBackupsToolStripMenuItem_Click);
|
||||
//
|
||||
// quickFiltersToolStripMenuItem
|
||||
//
|
||||
this.quickFiltersToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.firstFilterIsDefaultToolStripMenuItem,
|
||||
this.editQuickFiltersToolStripMenuItem,
|
||||
this.toolStripSeparator1});
|
||||
this.quickFiltersToolStripMenuItem.Name = "quickFiltersToolStripMenuItem";
|
||||
this.quickFiltersToolStripMenuItem.Size = new System.Drawing.Size(84, 20);
|
||||
this.quickFiltersToolStripMenuItem.Text = "Quick &Filters";
|
||||
//
|
||||
// firstFilterIsDefaultToolStripMenuItem
|
||||
//
|
||||
this.firstFilterIsDefaultToolStripMenuItem.Name = "firstFilterIsDefaultToolStripMenuItem";
|
||||
this.firstFilterIsDefaultToolStripMenuItem.Size = new System.Drawing.Size(256, 22);
|
||||
this.firstFilterIsDefaultToolStripMenuItem.Text = "Start Libation with 1st filter &Default";
|
||||
this.firstFilterIsDefaultToolStripMenuItem.Click += new System.EventHandler(this.FirstFilterIsDefaultToolStripMenuItem_Click);
|
||||
//
|
||||
// editQuickFiltersToolStripMenuItem
|
||||
//
|
||||
this.editQuickFiltersToolStripMenuItem.Name = "editQuickFiltersToolStripMenuItem";
|
||||
this.editQuickFiltersToolStripMenuItem.Size = new System.Drawing.Size(256, 22);
|
||||
this.editQuickFiltersToolStripMenuItem.Text = "&Edit quick filters";
|
||||
this.editQuickFiltersToolStripMenuItem.Click += new System.EventHandler(this.EditQuickFiltersToolStripMenuItem_Click);
|
||||
//
|
||||
// toolStripSeparator1
|
||||
//
|
||||
this.toolStripSeparator1.Name = "toolStripSeparator1";
|
||||
this.toolStripSeparator1.Size = new System.Drawing.Size(253, 6);
|
||||
//
|
||||
// settingsToolStripMenuItem
|
||||
//
|
||||
this.settingsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.basicSettingsToolStripMenuItem,
|
||||
this.advancedSettingsToolStripMenuItem});
|
||||
this.settingsToolStripMenuItem.Name = "settingsToolStripMenuItem";
|
||||
this.settingsToolStripMenuItem.Size = new System.Drawing.Size(61, 20);
|
||||
this.settingsToolStripMenuItem.Text = "&Settings";
|
||||
//
|
||||
// basicSettingsToolStripMenuItem
|
||||
//
|
||||
this.basicSettingsToolStripMenuItem.Name = "basicSettingsToolStripMenuItem";
|
||||
this.basicSettingsToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
|
||||
this.basicSettingsToolStripMenuItem.Text = "&Basic Settings";
|
||||
this.basicSettingsToolStripMenuItem.Click += new System.EventHandler(this.basicSettingsToolStripMenuItem_Click);
|
||||
//
|
||||
// advancedSettingsToolStripMenuItem
|
||||
//
|
||||
this.advancedSettingsToolStripMenuItem.Name = "advancedSettingsToolStripMenuItem";
|
||||
this.advancedSettingsToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
|
||||
this.advancedSettingsToolStripMenuItem.Text = "&Advanced Settings";
|
||||
this.advancedSettingsToolStripMenuItem.Click += new System.EventHandler(this.advancedSettingsToolStripMenuItem_Click);
|
||||
//
|
||||
// statusStrip1
|
||||
//
|
||||
this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.visibleCountLbl,
|
||||
this.springLbl,
|
||||
this.backupsCountsLbl,
|
||||
this.pdfsCountsLbl});
|
||||
this.statusStrip1.Location = new System.Drawing.Point(0, 445);
|
||||
this.statusStrip1.Name = "statusStrip1";
|
||||
this.statusStrip1.Size = new System.Drawing.Size(863, 22);
|
||||
this.statusStrip1.TabIndex = 6;
|
||||
this.statusStrip1.Text = "statusStrip1";
|
||||
//
|
||||
// visibleCountLbl
|
||||
//
|
||||
this.visibleCountLbl.Name = "visibleCountLbl";
|
||||
this.visibleCountLbl.Size = new System.Drawing.Size(61, 17);
|
||||
this.visibleCountLbl.Text = "Visible: {0}";
|
||||
//
|
||||
// springLbl
|
||||
//
|
||||
this.springLbl.Name = "springLbl";
|
||||
this.springLbl.Size = new System.Drawing.Size(232, 17);
|
||||
this.springLbl.Spring = true;
|
||||
//
|
||||
// backupsCountsLbl
|
||||
//
|
||||
this.backupsCountsLbl.Name = "backupsCountsLbl";
|
||||
this.backupsCountsLbl.Size = new System.Drawing.Size(336, 17);
|
||||
this.backupsCountsLbl.Text = "BACKUPS: No progress: {0} Encrypted: {1} Fully backed up: {2}";
|
||||
//
|
||||
// pdfsCountsLbl
|
||||
//
|
||||
this.pdfsCountsLbl.Name = "pdfsCountsLbl";
|
||||
this.pdfsCountsLbl.Size = new System.Drawing.Size(219, 17);
|
||||
this.pdfsCountsLbl.Text = "| PDFs: NOT d/l\'ed: {0} Downloaded: {1}";
|
||||
//
|
||||
// addFilterBtn
|
||||
//
|
||||
this.addFilterBtn.Location = new System.Drawing.Point(40, 27);
|
||||
this.addFilterBtn.Name = "addFilterBtn";
|
||||
this.addFilterBtn.Size = new System.Drawing.Size(140, 23);
|
||||
this.addFilterBtn.TabIndex = 4;
|
||||
this.addFilterBtn.Text = "Add To Quick Filters";
|
||||
this.addFilterBtn.UseVisualStyleBackColor = true;
|
||||
this.addFilterBtn.Click += new System.EventHandler(this.AddFilterBtn_Click);
|
||||
//
|
||||
// Form1
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(863, 467);
|
||||
this.Controls.Add(this.filterBtn);
|
||||
this.Controls.Add(this.addFilterBtn);
|
||||
this.Controls.Add(this.filterSearchTb);
|
||||
this.Controls.Add(this.filterHelpBtn);
|
||||
this.Controls.Add(this.statusStrip1);
|
||||
this.Controls.Add(this.gridPanel);
|
||||
this.Controls.Add(this.menuStrip1);
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.MainMenuStrip = this.menuStrip1;
|
||||
this.Name = "Form1";
|
||||
this.Text = "Libation: Liberate your Library";
|
||||
this.Load += new System.EventHandler(this.Form1_Load);
|
||||
this.menuStrip1.ResumeLayout(false);
|
||||
this.menuStrip1.PerformLayout();
|
||||
this.statusStrip1.ResumeLayout(false);
|
||||
this.statusStrip1.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
private System.Windows.Forms.Panel gridPanel;
|
||||
private System.Windows.Forms.MenuStrip menuStrip1;
|
||||
private System.Windows.Forms.ToolStripMenuItem importToolStripMenuItem;
|
||||
private System.Windows.Forms.StatusStrip statusStrip1;
|
||||
private System.Windows.Forms.ToolStripStatusLabel springLbl;
|
||||
private System.Windows.Forms.ToolStripStatusLabel visibleCountLbl;
|
||||
private System.Windows.Forms.ToolStripMenuItem liberateToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripStatusLabel backupsCountsLbl;
|
||||
private System.Windows.Forms.ToolStripMenuItem beginBookBackupsToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripStatusLabel pdfsCountsLbl;
|
||||
private System.Windows.Forms.ToolStripMenuItem beginPdfBackupsToolStripMenuItem;
|
||||
private System.Windows.Forms.TextBox filterSearchTb;
|
||||
private System.Windows.Forms.Button filterBtn;
|
||||
private System.Windows.Forms.Button filterHelpBtn;
|
||||
private System.Windows.Forms.ToolStripMenuItem settingsToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem scanLibraryToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem quickFiltersToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem firstFilterIsDefaultToolStripMenuItem;
|
||||
private System.Windows.Forms.Button addFilterBtn;
|
||||
private System.Windows.Forms.ToolStripMenuItem editQuickFiltersToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
|
||||
private System.Windows.Forms.ToolStripMenuItem basicSettingsToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem advancedSettingsToolStripMenuItem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using ApplicationServices;
|
||||
using DataLayer;
|
||||
using Dinah.Core;
|
||||
using Dinah.Core.Collections.Generic;
|
||||
using Dinah.Core.Drawing;
|
||||
using Dinah.Core.Windows.Forms;
|
||||
using FileManager;
|
||||
using LibationWinForms.Dialogs;
|
||||
|
||||
namespace LibationWinForm
|
||||
namespace LibationWinForms
|
||||
{
|
||||
public partial class Form1 : Form
|
||||
{
|
||||
// initial call here will initiate config loading
|
||||
private Configuration config { get; } = Configuration.Instance;
|
||||
|
||||
private string backupsCountsLbl_Format { get; }
|
||||
private string pdfsCountsLbl_Format { get; }
|
||||
private string visibleCountLbl_Format { get; }
|
||||
@@ -39,9 +36,6 @@ namespace LibationWinForm
|
||||
|
||||
private void Form1_Load(object sender, EventArgs e)
|
||||
{
|
||||
// call static ctor. There are bad race conditions if static ctor is first executed when we're running in parallel in setBackupCountsAsync()
|
||||
var foo = FilePathCache.JsonFile;
|
||||
|
||||
// load default/missing cover images. this will also initiate the background image downloader
|
||||
var format = System.Drawing.Imaging.ImageFormat.Jpeg;
|
||||
PictureStorage.SetDefaultImage(PictureSize._80x80, Properties.Resources.default_cover_80x80.ToBytes(format));
|
||||
@@ -59,7 +53,7 @@ namespace LibationWinForm
|
||||
backupsCountsLbl.Text = "[Calculating backed up book quantities]";
|
||||
pdfsCountsLbl.Text = "[Calculating backed up PDFs]";
|
||||
|
||||
setBackupCounts();
|
||||
setBackupCounts(null, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,32 +80,35 @@ namespace LibationWinForm
|
||||
{
|
||||
gridPanel.Controls.Remove(currProductsGrid);
|
||||
currProductsGrid.VisibleCountChanged -= setVisibleCount;
|
||||
currProductsGrid.BackupCountsChanged -= setBackupCounts;
|
||||
currProductsGrid.Dispose();
|
||||
}
|
||||
|
||||
currProductsGrid = new ProductsGrid { Dock = DockStyle.Fill };
|
||||
currProductsGrid.VisibleCountChanged += setVisibleCount;
|
||||
currProductsGrid.BackupCountsChanged += setBackupCounts;
|
||||
gridPanel.Controls.Add(currProductsGrid);
|
||||
currProductsGrid.Display();
|
||||
}
|
||||
ResumeLayout();
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region bottom: qty books visible
|
||||
private void setVisibleCount(object _, int qty) => visibleCountLbl.Text = string.Format(visibleCountLbl_Format, qty);
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region bottom: backup counts
|
||||
private void setBackupCounts()
|
||||
#region bottom: backup counts
|
||||
private void setBackupCounts(object _, object __)
|
||||
{
|
||||
var books = LibraryQueries.GetLibrary_Flat_NoTracking()
|
||||
var books = DbContexts.GetContext()
|
||||
.GetLibrary_Flat_NoTracking()
|
||||
.Select(sp => sp.Book)
|
||||
.ToList();
|
||||
|
||||
setBookBackupCounts(books);
|
||||
setPdfBackupCounts(books);
|
||||
}
|
||||
}
|
||||
enum AudioFileState { full, aax, none }
|
||||
private void setBookBackupCounts(IEnumerable<Book> books)
|
||||
{
|
||||
@@ -175,8 +172,8 @@ namespace LibationWinForm
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region filter
|
||||
private void filterHelpBtn_Click(object sender, EventArgs e) => new Dialogs.SearchSyntaxDialog().ShowDialog();
|
||||
#region filter
|
||||
private void filterHelpBtn_Click(object sender, EventArgs e) => new Dialogs.SearchSyntaxDialog().ShowDialog();
|
||||
|
||||
private void AddFilterBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
@@ -233,33 +230,25 @@ namespace LibationWinForm
|
||||
|
||||
MessageBox.Show($"Total processed: {totalProcessed}\r\nNew: {newAdded}");
|
||||
|
||||
// update backup counts if we have new library items
|
||||
if (newAdded > 0)
|
||||
setBackupCounts();
|
||||
|
||||
if (totalProcessed > 0)
|
||||
reloadGrid();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region liberate menu
|
||||
private void setBackupCounts(object _, string __) => setBackupCounts();
|
||||
#endregion
|
||||
|
||||
#region liberate menu
|
||||
private async void beginBookBackupsToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
var backupBook = BookLiberation.ProcessorAutomationController.GetWiredUpBackupBook();
|
||||
backupBook.DownloadBook.Completed += setBackupCounts;
|
||||
backupBook.DecryptBook.Completed += setBackupCounts;
|
||||
backupBook.DownloadPdf.Completed += setBackupCounts;
|
||||
await BookLiberation.ProcessorAutomationController.RunAutomaticBackup(backupBook);
|
||||
var backupBook = BookLiberation.ProcessorAutomationController.GetWiredUpBackupBook(updateGridRow);
|
||||
await BookLiberation.ProcessorAutomationController.RunAutomaticBackupAsync(backupBook);
|
||||
}
|
||||
|
||||
private async void beginPdfBackupsToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
var downloadPdf = BookLiberation.ProcessorAutomationController.GetWiredUpDownloadPdf();
|
||||
downloadPdf.Completed += setBackupCounts;
|
||||
await BookLiberation.ProcessorAutomationController.RunAutomaticDownload(downloadPdf);
|
||||
var downloadPdf = BookLiberation.ProcessorAutomationController.GetWiredUpDownloadPdf(updateGridRow);
|
||||
await BookLiberation.ProcessorAutomationController.RunAutomaticDownloadAsync(downloadPdf);
|
||||
}
|
||||
|
||||
private void updateGridRow(object _, LibraryBook libraryBook) => currProductsGrid.RefreshRow(libraryBook.Book.AudibleProductId);
|
||||
#endregion
|
||||
|
||||
#region quick filters menu
|
||||
@@ -310,8 +299,26 @@ namespace LibationWinForm
|
||||
private void EditQuickFiltersToolStripMenuItem_Click(object sender, EventArgs e) => new Dialogs.EditQuickFilters(this).ShowDialog();
|
||||
#endregion
|
||||
|
||||
#region settings menu item
|
||||
private void settingsToolStripMenuItem_Click(object sender, EventArgs e) => new SettingsDialog().ShowDialog();
|
||||
#region settings menu
|
||||
private void basicSettingsToolStripMenuItem_Click(object sender, EventArgs e) => new SettingsDialog().ShowDialog();
|
||||
|
||||
private void advancedSettingsToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
var oldLocation = Configuration.Instance.LibationFiles;
|
||||
new LibationFilesDialog().ShowDialog();
|
||||
|
||||
// no change
|
||||
if (System.IO.Path.GetFullPath(oldLocation).EqualsInsensitive(System.IO.Path.GetFullPath(Configuration.Instance.LibationFiles)))
|
||||
return;
|
||||
|
||||
MessageBox.Show(
|
||||
"You have changed a file path important for this program. All files will remain in their original location; nothing will be moved. Libation must be restarted so these changes are handled correctly.",
|
||||
"Closing Libation",
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Exclamation);
|
||||
Application.Exit();
|
||||
Environment.Exit(0);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||