Merge branch 'rmcrackan:master' into master
This commit is contained in:
commit
30eb117fa1
@ -100,6 +100,9 @@ namespace ApplicationServices
|
|||||||
|
|
||||||
[Name("Content Type")]
|
[Name("Content Type")]
|
||||||
public string ContentType { get; set; }
|
public string ContentType { get; set; }
|
||||||
|
|
||||||
|
[Name("Audio Format")]
|
||||||
|
public string AudioFormat { get; set; }
|
||||||
}
|
}
|
||||||
public static class LibToDtos
|
public static class LibToDtos
|
||||||
{
|
{
|
||||||
@ -132,7 +135,8 @@ namespace ApplicationServices
|
|||||||
MyLibationTags = a.Book.UserDefinedItem.Tags,
|
MyLibationTags = a.Book.UserDefinedItem.Tags,
|
||||||
BookStatus = a.Book.UserDefinedItem.BookStatus.ToString(),
|
BookStatus = a.Book.UserDefinedItem.BookStatus.ToString(),
|
||||||
PdfStatus = a.Book.UserDefinedItem.PdfStatus.ToString(),
|
PdfStatus = a.Book.UserDefinedItem.PdfStatus.ToString(),
|
||||||
ContentType = a.Book.ContentType.ToString()
|
ContentType = a.Book.ContentType.ToString(),
|
||||||
|
AudioFormat = a.Book.AudioFormat.ToString()
|
||||||
}).ToList();
|
}).ToList();
|
||||||
}
|
}
|
||||||
public static class LibraryExporter
|
public static class LibraryExporter
|
||||||
@ -176,33 +180,34 @@ namespace ApplicationServices
|
|||||||
var row = sheet.CreateRow(rowIndex);
|
var row = sheet.CreateRow(rowIndex);
|
||||||
|
|
||||||
var columns = new[] {
|
var columns = new[] {
|
||||||
nameof (ExportDto.Account),
|
nameof(ExportDto.Account),
|
||||||
nameof (ExportDto.DateAdded),
|
nameof(ExportDto.DateAdded),
|
||||||
nameof (ExportDto.AudibleProductId),
|
nameof(ExportDto.AudibleProductId),
|
||||||
nameof (ExportDto.Locale),
|
nameof(ExportDto.Locale),
|
||||||
nameof (ExportDto.Title),
|
nameof(ExportDto.Title),
|
||||||
nameof (ExportDto.AuthorNames),
|
nameof(ExportDto.AuthorNames),
|
||||||
nameof (ExportDto.NarratorNames),
|
nameof(ExportDto.NarratorNames),
|
||||||
nameof (ExportDto.LengthInMinutes),
|
nameof(ExportDto.LengthInMinutes),
|
||||||
nameof (ExportDto.Description),
|
nameof(ExportDto.Description),
|
||||||
nameof (ExportDto.Publisher),
|
nameof(ExportDto.Publisher),
|
||||||
nameof (ExportDto.HasPdf),
|
nameof(ExportDto.HasPdf),
|
||||||
nameof (ExportDto.SeriesNames),
|
nameof(ExportDto.SeriesNames),
|
||||||
nameof (ExportDto.SeriesOrder),
|
nameof(ExportDto.SeriesOrder),
|
||||||
nameof (ExportDto.CommunityRatingOverall),
|
nameof(ExportDto.CommunityRatingOverall),
|
||||||
nameof (ExportDto.CommunityRatingPerformance),
|
nameof(ExportDto.CommunityRatingPerformance),
|
||||||
nameof (ExportDto.CommunityRatingStory),
|
nameof(ExportDto.CommunityRatingStory),
|
||||||
nameof (ExportDto.PictureId),
|
nameof(ExportDto.PictureId),
|
||||||
nameof (ExportDto.IsAbridged),
|
nameof(ExportDto.IsAbridged),
|
||||||
nameof (ExportDto.DatePublished),
|
nameof(ExportDto.DatePublished),
|
||||||
nameof (ExportDto.CategoriesNames),
|
nameof(ExportDto.CategoriesNames),
|
||||||
nameof (ExportDto.MyRatingOverall),
|
nameof(ExportDto.MyRatingOverall),
|
||||||
nameof (ExportDto.MyRatingPerformance),
|
nameof(ExportDto.MyRatingPerformance),
|
||||||
nameof (ExportDto.MyRatingStory),
|
nameof(ExportDto.MyRatingStory),
|
||||||
nameof (ExportDto.MyLibationTags),
|
nameof(ExportDto.MyLibationTags),
|
||||||
nameof (ExportDto.BookStatus),
|
nameof(ExportDto.BookStatus),
|
||||||
nameof (ExportDto.PdfStatus),
|
nameof(ExportDto.PdfStatus),
|
||||||
nameof (ExportDto.ContentType)
|
nameof(ExportDto.ContentType),
|
||||||
|
nameof(ExportDto.AudioFormat)
|
||||||
};
|
};
|
||||||
var col = 0;
|
var col = 0;
|
||||||
foreach (var c in columns)
|
foreach (var c in columns)
|
||||||
@ -268,6 +273,7 @@ namespace ApplicationServices
|
|||||||
row.CreateCell(col++).SetCellValue(dto.BookStatus);
|
row.CreateCell(col++).SetCellValue(dto.BookStatus);
|
||||||
row.CreateCell(col++).SetCellValue(dto.PdfStatus);
|
row.CreateCell(col++).SetCellValue(dto.PdfStatus);
|
||||||
row.CreateCell(col++).SetCellValue(dto.ContentType);
|
row.CreateCell(col++).SetCellValue(dto.ContentType);
|
||||||
|
row.CreateCell(col++).SetCellValue(dto.AudioFormat);
|
||||||
|
|
||||||
rowIndex++;
|
rowIndex++;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,7 +17,6 @@ namespace DataLayer
|
|||||||
|
|
||||||
public class AudioFormat : IComparable<AudioFormat>, IComparable
|
public class AudioFormat : IComparable<AudioFormat>, IComparable
|
||||||
{
|
{
|
||||||
|
|
||||||
internal int AudioFormatID { get; private set; }
|
internal int AudioFormatID { get; private set; }
|
||||||
public int Bitrate { get; private init; }
|
public int Bitrate { get; private init; }
|
||||||
public int SampleRate { get; private init; }
|
public int SampleRate { get; private init; }
|
||||||
|
|||||||
@ -37,7 +37,11 @@ namespace FileLiberator
|
|||||||
Narrators = libraryBook.Book.Narrators.Select(c => c.Name).ToList(),
|
Narrators = libraryBook.Book.Narrators.Select(c => c.Name).ToList(),
|
||||||
|
|
||||||
SeriesName = libraryBook.Book.SeriesLink.FirstOrDefault()?.Series.Name,
|
SeriesName = libraryBook.Book.SeriesLink.FirstOrDefault()?.Series.Name,
|
||||||
SeriesNumber = libraryBook.Book.SeriesLink.FirstOrDefault()?.Order
|
SeriesNumber = libraryBook.Book.SeriesLink.FirstOrDefault()?.Order,
|
||||||
|
|
||||||
|
BitRate = libraryBook.Book.AudioFormat.Bitrate,
|
||||||
|
SampleRate = libraryBook.Book.AudioFormat.SampleRate,
|
||||||
|
Channels = libraryBook.Book.AudioFormat.Channels,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,10 @@ namespace LibationFileManager
|
|||||||
|
|
||||||
public string SeriesName { get; set; }
|
public string SeriesName { get; set; }
|
||||||
public string SeriesNumber { get; set; }
|
public string SeriesNumber { get; set; }
|
||||||
|
|
||||||
|
public int BitRate { get; set; }
|
||||||
|
public int SampleRate { get; set; }
|
||||||
|
public int Channels { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LibraryBookDto : BookDto
|
public class LibraryBookDto : BookDto
|
||||||
|
|||||||
@ -34,6 +34,9 @@ namespace LibationFileManager
|
|||||||
public static TemplateTags Series { get; } = new TemplateTags("series", "Name of series");
|
public static TemplateTags Series { get; } = new TemplateTags("series", "Name of series");
|
||||||
// can't also have a leading zeros version. Too many weird edge cases. Eg: "1-4"
|
// can't also have a leading zeros version. Too many weird edge cases. Eg: "1-4"
|
||||||
public static TemplateTags SeriesNumber { get; } = new TemplateTags("series#", "Number order in series");
|
public static TemplateTags SeriesNumber { get; } = new TemplateTags("series#", "Number order in series");
|
||||||
|
public static TemplateTags Bitrate { get; } = new TemplateTags("bitrate", "File's orig. bitrate");
|
||||||
|
public static TemplateTags SampleRate { get; } = new TemplateTags("samplerate", "File's orig. sample rate");
|
||||||
|
public static TemplateTags Channels { get; } = new TemplateTags("channels", "Number of audio channels");
|
||||||
public static TemplateTags Account { get; } = new TemplateTags("account", "Audible account of this book");
|
public static TemplateTags Account { get; } = new TemplateTags("account", "Audible account of this book");
|
||||||
public static TemplateTags Locale { get; } = new TemplateTags("locale", "Region/country");
|
public static TemplateTags Locale { get; } = new TemplateTags("locale", "Region/country");
|
||||||
|
|
||||||
|
|||||||
@ -137,6 +137,9 @@ namespace LibationFileManager
|
|||||||
fileNamingTemplate.AddParameterReplacement(TemplateTags.FirstNarrator, libraryBookDto.FirstNarrator);
|
fileNamingTemplate.AddParameterReplacement(TemplateTags.FirstNarrator, libraryBookDto.FirstNarrator);
|
||||||
fileNamingTemplate.AddParameterReplacement(TemplateTags.Series, libraryBookDto.SeriesName);
|
fileNamingTemplate.AddParameterReplacement(TemplateTags.Series, libraryBookDto.SeriesName);
|
||||||
fileNamingTemplate.AddParameterReplacement(TemplateTags.SeriesNumber, libraryBookDto.SeriesNumber);
|
fileNamingTemplate.AddParameterReplacement(TemplateTags.SeriesNumber, libraryBookDto.SeriesNumber);
|
||||||
|
fileNamingTemplate.AddParameterReplacement(TemplateTags.Bitrate, libraryBookDto.BitRate);
|
||||||
|
fileNamingTemplate.AddParameterReplacement(TemplateTags.SampleRate, libraryBookDto.SampleRate);
|
||||||
|
fileNamingTemplate.AddParameterReplacement(TemplateTags.Channels, libraryBookDto.Channels);
|
||||||
fileNamingTemplate.AddParameterReplacement(TemplateTags.Account, libraryBookDto.Account);
|
fileNamingTemplate.AddParameterReplacement(TemplateTags.Account, libraryBookDto.Account);
|
||||||
fileNamingTemplate.AddParameterReplacement(TemplateTags.Locale, libraryBookDto.Locale);
|
fileNamingTemplate.AddParameterReplacement(TemplateTags.Locale, libraryBookDto.Locale);
|
||||||
|
|
||||||
|
|||||||
@ -28,193 +28,206 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeComponent()
|
private void InitializeComponent()
|
||||||
{
|
{
|
||||||
this.saveBtn = new System.Windows.Forms.Button();
|
this.saveBtn = new System.Windows.Forms.Button();
|
||||||
this.newTagsTb = new System.Windows.Forms.TextBox();
|
this.newTagsTb = new System.Windows.Forms.TextBox();
|
||||||
this.tagsDescLbl = new System.Windows.Forms.Label();
|
this.tagsDescLbl = new System.Windows.Forms.Label();
|
||||||
this.coverPb = new System.Windows.Forms.PictureBox();
|
this.coverPb = new System.Windows.Forms.PictureBox();
|
||||||
this.detailsTb = new System.Windows.Forms.TextBox();
|
this.detailsTb = new System.Windows.Forms.TextBox();
|
||||||
this.tagsGb = new System.Windows.Forms.GroupBox();
|
this.tagsGb = new System.Windows.Forms.GroupBox();
|
||||||
this.cancelBtn = new System.Windows.Forms.Button();
|
this.cancelBtn = new System.Windows.Forms.Button();
|
||||||
this.liberatedGb = new System.Windows.Forms.GroupBox();
|
this.liberatedGb = new System.Windows.Forms.GroupBox();
|
||||||
this.pdfLiberatedCb = new System.Windows.Forms.ComboBox();
|
this.pdfLiberatedCb = new System.Windows.Forms.ComboBox();
|
||||||
this.pdfLiberatedLbl = new System.Windows.Forms.Label();
|
this.pdfLiberatedLbl = new System.Windows.Forms.Label();
|
||||||
this.bookLiberatedCb = new System.Windows.Forms.ComboBox();
|
this.bookLiberatedCb = new System.Windows.Forms.ComboBox();
|
||||||
this.bookLiberatedLbl = new System.Windows.Forms.Label();
|
this.bookLiberatedLbl = new System.Windows.Forms.Label();
|
||||||
this.liberatedDescLbl = new System.Windows.Forms.Label();
|
this.liberatedDescLbl = new System.Windows.Forms.Label();
|
||||||
((System.ComponentModel.ISupportInitialize)(this.coverPb)).BeginInit();
|
this.audibleLink = new System.Windows.Forms.LinkLabel();
|
||||||
this.tagsGb.SuspendLayout();
|
((System.ComponentModel.ISupportInitialize)(this.coverPb)).BeginInit();
|
||||||
this.liberatedGb.SuspendLayout();
|
this.tagsGb.SuspendLayout();
|
||||||
this.SuspendLayout();
|
this.liberatedGb.SuspendLayout();
|
||||||
//
|
this.SuspendLayout();
|
||||||
// saveBtn
|
//
|
||||||
//
|
// 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(376, 427);
|
this.saveBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.saveBtn.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
this.saveBtn.Location = new System.Drawing.Point(376, 427);
|
||||||
this.saveBtn.Name = "saveBtn";
|
this.saveBtn.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||||
this.saveBtn.Size = new System.Drawing.Size(88, 27);
|
this.saveBtn.Name = "saveBtn";
|
||||||
this.saveBtn.TabIndex = 3;
|
this.saveBtn.Size = new System.Drawing.Size(88, 27);
|
||||||
this.saveBtn.Text = "Save";
|
this.saveBtn.TabIndex = 4;
|
||||||
this.saveBtn.UseVisualStyleBackColor = true;
|
this.saveBtn.Text = "Save";
|
||||||
this.saveBtn.Click += new System.EventHandler(this.saveBtn_Click);
|
this.saveBtn.UseVisualStyleBackColor = true;
|
||||||
//
|
this.saveBtn.Click += new System.EventHandler(this.saveBtn_Click);
|
||||||
// newTagsTb
|
//
|
||||||
//
|
// newTagsTb
|
||||||
this.newTagsTb.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
//
|
||||||
|
this.newTagsTb.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.newTagsTb.Location = new System.Drawing.Point(7, 40);
|
this.newTagsTb.Location = new System.Drawing.Point(7, 40);
|
||||||
this.newTagsTb.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
this.newTagsTb.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||||
this.newTagsTb.Name = "newTagsTb";
|
this.newTagsTb.Name = "newTagsTb";
|
||||||
this.newTagsTb.ScrollBars = System.Windows.Forms.ScrollBars.Both;
|
this.newTagsTb.ScrollBars = System.Windows.Forms.ScrollBars.Both;
|
||||||
this.newTagsTb.Size = new System.Drawing.Size(556, 23);
|
this.newTagsTb.Size = new System.Drawing.Size(556, 23);
|
||||||
this.newTagsTb.TabIndex = 1;
|
this.newTagsTb.TabIndex = 1;
|
||||||
//
|
//
|
||||||
// tagsDescLbl
|
// tagsDescLbl
|
||||||
//
|
//
|
||||||
this.tagsDescLbl.AutoSize = true;
|
this.tagsDescLbl.AutoSize = true;
|
||||||
this.tagsDescLbl.Location = new System.Drawing.Point(7, 19);
|
this.tagsDescLbl.Location = new System.Drawing.Point(7, 19);
|
||||||
this.tagsDescLbl.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
this.tagsDescLbl.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||||
this.tagsDescLbl.Name = "tagsDescLbl";
|
this.tagsDescLbl.Name = "tagsDescLbl";
|
||||||
this.tagsDescLbl.Size = new System.Drawing.Size(458, 15);
|
this.tagsDescLbl.Size = new System.Drawing.Size(458, 15);
|
||||||
this.tagsDescLbl.TabIndex = 0;
|
this.tagsDescLbl.TabIndex = 0;
|
||||||
this.tagsDescLbl.Text = "Tags are separated by a space. Each tag can contain letters, numbers, and undersc" +
|
this.tagsDescLbl.Text = "Tags are separated by a space. Each tag can contain letters, numbers, and undersc" +
|
||||||
"ores";
|
"ores";
|
||||||
//
|
//
|
||||||
// coverPb
|
// coverPb
|
||||||
//
|
//
|
||||||
this.coverPb.Location = new System.Drawing.Point(12, 12);
|
this.coverPb.Location = new System.Drawing.Point(12, 12);
|
||||||
this.coverPb.Name = "coverPb";
|
this.coverPb.Name = "coverPb";
|
||||||
this.coverPb.Size = new System.Drawing.Size(80, 80);
|
this.coverPb.Size = new System.Drawing.Size(80, 80);
|
||||||
this.coverPb.TabIndex = 3;
|
this.coverPb.TabIndex = 3;
|
||||||
this.coverPb.TabStop = false;
|
this.coverPb.TabStop = false;
|
||||||
//
|
//
|
||||||
// detailsTb
|
// detailsTb
|
||||||
//
|
//
|
||||||
this.detailsTb.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
this.detailsTb.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
| System.Windows.Forms.AnchorStyles.Left)
|
| System.Windows.Forms.AnchorStyles.Left)
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.detailsTb.Location = new System.Drawing.Point(98, 12);
|
this.detailsTb.Location = new System.Drawing.Point(98, 12);
|
||||||
this.detailsTb.Multiline = true;
|
this.detailsTb.Multiline = true;
|
||||||
this.detailsTb.Name = "detailsTb";
|
this.detailsTb.Name = "detailsTb";
|
||||||
this.detailsTb.ReadOnly = true;
|
this.detailsTb.ReadOnly = true;
|
||||||
this.detailsTb.ScrollBars = System.Windows.Forms.ScrollBars.Both;
|
this.detailsTb.ScrollBars = System.Windows.Forms.ScrollBars.Both;
|
||||||
this.detailsTb.Size = new System.Drawing.Size(484, 202);
|
this.detailsTb.Size = new System.Drawing.Size(484, 202);
|
||||||
this.detailsTb.TabIndex = 1;
|
this.detailsTb.TabIndex = 1;
|
||||||
//
|
//
|
||||||
// tagsGb
|
// tagsGb
|
||||||
//
|
//
|
||||||
this.tagsGb.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
this.tagsGb.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.tagsGb.Controls.Add(this.tagsDescLbl);
|
this.tagsGb.Controls.Add(this.tagsDescLbl);
|
||||||
this.tagsGb.Controls.Add(this.newTagsTb);
|
this.tagsGb.Controls.Add(this.newTagsTb);
|
||||||
this.tagsGb.Location = new System.Drawing.Point(12, 220);
|
this.tagsGb.Location = new System.Drawing.Point(12, 220);
|
||||||
this.tagsGb.Name = "tagsGb";
|
this.tagsGb.Name = "tagsGb";
|
||||||
this.tagsGb.Size = new System.Drawing.Size(570, 73);
|
this.tagsGb.Size = new System.Drawing.Size(570, 73);
|
||||||
this.tagsGb.TabIndex = 0;
|
this.tagsGb.TabIndex = 2;
|
||||||
this.tagsGb.TabStop = false;
|
this.tagsGb.TabStop = false;
|
||||||
this.tagsGb.Text = "Edit Tags";
|
this.tagsGb.Text = "Edit Tags";
|
||||||
//
|
//
|
||||||
// cancelBtn
|
// cancelBtn
|
||||||
//
|
//
|
||||||
this.cancelBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
this.cancelBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.cancelBtn.Location = new System.Drawing.Point(494, 427);
|
this.cancelBtn.Location = new System.Drawing.Point(494, 427);
|
||||||
this.cancelBtn.Name = "cancelBtn";
|
this.cancelBtn.Name = "cancelBtn";
|
||||||
this.cancelBtn.Size = new System.Drawing.Size(88, 27);
|
this.cancelBtn.Size = new System.Drawing.Size(88, 27);
|
||||||
this.cancelBtn.TabIndex = 4;
|
this.cancelBtn.TabIndex = 5;
|
||||||
this.cancelBtn.Text = "Cancel";
|
this.cancelBtn.Text = "Cancel";
|
||||||
this.cancelBtn.UseVisualStyleBackColor = true;
|
this.cancelBtn.UseVisualStyleBackColor = true;
|
||||||
this.cancelBtn.Click += new System.EventHandler(this.cancelBtn_Click);
|
this.cancelBtn.Click += new System.EventHandler(this.cancelBtn_Click);
|
||||||
//
|
//
|
||||||
// liberatedGb
|
// liberatedGb
|
||||||
//
|
//
|
||||||
this.liberatedGb.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
this.liberatedGb.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.liberatedGb.Controls.Add(this.pdfLiberatedCb);
|
this.liberatedGb.Controls.Add(this.pdfLiberatedCb);
|
||||||
this.liberatedGb.Controls.Add(this.pdfLiberatedLbl);
|
this.liberatedGb.Controls.Add(this.pdfLiberatedLbl);
|
||||||
this.liberatedGb.Controls.Add(this.bookLiberatedCb);
|
this.liberatedGb.Controls.Add(this.bookLiberatedCb);
|
||||||
this.liberatedGb.Controls.Add(this.bookLiberatedLbl);
|
this.liberatedGb.Controls.Add(this.bookLiberatedLbl);
|
||||||
this.liberatedGb.Controls.Add(this.liberatedDescLbl);
|
this.liberatedGb.Controls.Add(this.liberatedDescLbl);
|
||||||
this.liberatedGb.Location = new System.Drawing.Point(12, 299);
|
this.liberatedGb.Location = new System.Drawing.Point(12, 299);
|
||||||
this.liberatedGb.Name = "liberatedGb";
|
this.liberatedGb.Name = "liberatedGb";
|
||||||
this.liberatedGb.Size = new System.Drawing.Size(570, 122);
|
this.liberatedGb.Size = new System.Drawing.Size(570, 122);
|
||||||
this.liberatedGb.TabIndex = 2;
|
this.liberatedGb.TabIndex = 3;
|
||||||
this.liberatedGb.TabStop = false;
|
this.liberatedGb.TabStop = false;
|
||||||
this.liberatedGb.Text = "Liberated status: Whether the book/pdf has been downloaded";
|
this.liberatedGb.Text = "Liberated status: Whether the book/pdf has been downloaded";
|
||||||
//
|
//
|
||||||
// pdfLiberatedCb
|
// pdfLiberatedCb
|
||||||
//
|
//
|
||||||
this.pdfLiberatedCb.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
this.pdfLiberatedCb.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||||
this.pdfLiberatedCb.FormattingEnabled = true;
|
this.pdfLiberatedCb.FormattingEnabled = true;
|
||||||
this.pdfLiberatedCb.Location = new System.Drawing.Point(244, 86);
|
this.pdfLiberatedCb.Location = new System.Drawing.Point(244, 86);
|
||||||
this.pdfLiberatedCb.Name = "pdfLiberatedCb";
|
this.pdfLiberatedCb.Name = "pdfLiberatedCb";
|
||||||
this.pdfLiberatedCb.Size = new System.Drawing.Size(121, 23);
|
this.pdfLiberatedCb.Size = new System.Drawing.Size(121, 23);
|
||||||
this.pdfLiberatedCb.TabIndex = 4;
|
this.pdfLiberatedCb.TabIndex = 4;
|
||||||
//
|
//
|
||||||
// pdfLiberatedLbl
|
// pdfLiberatedLbl
|
||||||
//
|
//
|
||||||
this.pdfLiberatedLbl.AutoSize = true;
|
this.pdfLiberatedLbl.AutoSize = true;
|
||||||
this.pdfLiberatedLbl.Location = new System.Drawing.Point(210, 89);
|
this.pdfLiberatedLbl.Location = new System.Drawing.Point(210, 89);
|
||||||
this.pdfLiberatedLbl.Name = "pdfLiberatedLbl";
|
this.pdfLiberatedLbl.Name = "pdfLiberatedLbl";
|
||||||
this.pdfLiberatedLbl.Size = new System.Drawing.Size(28, 15);
|
this.pdfLiberatedLbl.Size = new System.Drawing.Size(28, 15);
|
||||||
this.pdfLiberatedLbl.TabIndex = 3;
|
this.pdfLiberatedLbl.TabIndex = 3;
|
||||||
this.pdfLiberatedLbl.Text = "PDF";
|
this.pdfLiberatedLbl.Text = "PDF";
|
||||||
//
|
//
|
||||||
// bookLiberatedCb
|
// bookLiberatedCb
|
||||||
//
|
//
|
||||||
this.bookLiberatedCb.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
this.bookLiberatedCb.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||||
this.bookLiberatedCb.FormattingEnabled = true;
|
this.bookLiberatedCb.FormattingEnabled = true;
|
||||||
this.bookLiberatedCb.Location = new System.Drawing.Point(47, 86);
|
this.bookLiberatedCb.Location = new System.Drawing.Point(47, 86);
|
||||||
this.bookLiberatedCb.Name = "bookLiberatedCb";
|
this.bookLiberatedCb.Name = "bookLiberatedCb";
|
||||||
this.bookLiberatedCb.Size = new System.Drawing.Size(121, 23);
|
this.bookLiberatedCb.Size = new System.Drawing.Size(121, 23);
|
||||||
this.bookLiberatedCb.TabIndex = 2;
|
this.bookLiberatedCb.TabIndex = 2;
|
||||||
//
|
//
|
||||||
// bookLiberatedLbl
|
// bookLiberatedLbl
|
||||||
//
|
//
|
||||||
this.bookLiberatedLbl.AutoSize = true;
|
this.bookLiberatedLbl.AutoSize = true;
|
||||||
this.bookLiberatedLbl.Location = new System.Drawing.Point(7, 89);
|
this.bookLiberatedLbl.Location = new System.Drawing.Point(7, 89);
|
||||||
this.bookLiberatedLbl.Name = "bookLiberatedLbl";
|
this.bookLiberatedLbl.Name = "bookLiberatedLbl";
|
||||||
this.bookLiberatedLbl.Size = new System.Drawing.Size(34, 15);
|
this.bookLiberatedLbl.Size = new System.Drawing.Size(34, 15);
|
||||||
this.bookLiberatedLbl.TabIndex = 1;
|
this.bookLiberatedLbl.TabIndex = 1;
|
||||||
this.bookLiberatedLbl.Text = "Book";
|
this.bookLiberatedLbl.Text = "Book";
|
||||||
//
|
//
|
||||||
// liberatedDescLbl
|
// liberatedDescLbl
|
||||||
//
|
//
|
||||||
this.liberatedDescLbl.AutoSize = true;
|
this.liberatedDescLbl.AutoSize = true;
|
||||||
this.liberatedDescLbl.Location = new System.Drawing.Point(20, 31);
|
this.liberatedDescLbl.Location = new System.Drawing.Point(20, 31);
|
||||||
this.liberatedDescLbl.Name = "liberatedDescLbl";
|
this.liberatedDescLbl.Name = "liberatedDescLbl";
|
||||||
this.liberatedDescLbl.Size = new System.Drawing.Size(312, 30);
|
this.liberatedDescLbl.Size = new System.Drawing.Size(312, 30);
|
||||||
this.liberatedDescLbl.TabIndex = 0;
|
this.liberatedDescLbl.TabIndex = 0;
|
||||||
this.liberatedDescLbl.Text = "To download again next time: change to Not Downloaded\r\nTo not download: change to" +
|
this.liberatedDescLbl.Text = "To download again next time: change to Not Downloaded\r\nTo not download: change to" +
|
||||||
" Downloaded";
|
" Downloaded";
|
||||||
//
|
//
|
||||||
// BookDetailsDialog
|
// audibleLink
|
||||||
//
|
//
|
||||||
this.AcceptButton = this.saveBtn;
|
this.audibleLink.AutoSize = true;
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
|
this.audibleLink.Location = new System.Drawing.Point(12, 169);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.audibleLink.Name = "audibleLink";
|
||||||
this.CancelButton = this.cancelBtn;
|
this.audibleLink.Size = new System.Drawing.Size(57, 45);
|
||||||
this.ClientSize = new System.Drawing.Size(594, 466);
|
this.audibleLink.TabIndex = 0;
|
||||||
this.Controls.Add(this.liberatedGb);
|
this.audibleLink.TabStop = true;
|
||||||
this.Controls.Add(this.cancelBtn);
|
this.audibleLink.Text = "Open in\r\nAudible\r\n(browser)";
|
||||||
this.Controls.Add(this.tagsGb);
|
this.audibleLink.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.audibleLink_LinkClicked);
|
||||||
this.Controls.Add(this.detailsTb);
|
//
|
||||||
this.Controls.Add(this.coverPb);
|
// BookDetailsDialog
|
||||||
this.Controls.Add(this.saveBtn);
|
//
|
||||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
|
this.AcceptButton = this.saveBtn;
|
||||||
this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
|
||||||
this.MaximizeBox = false;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.MinimizeBox = false;
|
this.CancelButton = this.cancelBtn;
|
||||||
this.Name = "BookDetailsDialog";
|
this.ClientSize = new System.Drawing.Size(594, 466);
|
||||||
this.ShowInTaskbar = false;
|
this.Controls.Add(this.audibleLink);
|
||||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
this.Controls.Add(this.liberatedGb);
|
||||||
this.Text = "Book Details";
|
this.Controls.Add(this.cancelBtn);
|
||||||
((System.ComponentModel.ISupportInitialize)(this.coverPb)).EndInit();
|
this.Controls.Add(this.tagsGb);
|
||||||
this.tagsGb.ResumeLayout(false);
|
this.Controls.Add(this.detailsTb);
|
||||||
this.tagsGb.PerformLayout();
|
this.Controls.Add(this.coverPb);
|
||||||
this.liberatedGb.ResumeLayout(false);
|
this.Controls.Add(this.saveBtn);
|
||||||
this.liberatedGb.PerformLayout();
|
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
|
||||||
this.ResumeLayout(false);
|
this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||||
this.PerformLayout();
|
this.MaximizeBox = false;
|
||||||
|
this.MinimizeBox = false;
|
||||||
|
this.Name = "BookDetailsDialog";
|
||||||
|
this.ShowInTaskbar = false;
|
||||||
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||||
|
this.Text = "Book Details";
|
||||||
|
((System.ComponentModel.ISupportInitialize)(this.coverPb)).EndInit();
|
||||||
|
this.tagsGb.ResumeLayout(false);
|
||||||
|
this.tagsGb.PerformLayout();
|
||||||
|
this.liberatedGb.ResumeLayout(false);
|
||||||
|
this.liberatedGb.PerformLayout();
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
this.PerformLayout();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,5 +245,6 @@
|
|||||||
private System.Windows.Forms.ComboBox bookLiberatedCb;
|
private System.Windows.Forms.ComboBox bookLiberatedCb;
|
||||||
private System.Windows.Forms.Label bookLiberatedLbl;
|
private System.Windows.Forms.Label bookLiberatedLbl;
|
||||||
private System.Windows.Forms.Label liberatedDescLbl;
|
private System.Windows.Forms.Label liberatedDescLbl;
|
||||||
}
|
private System.Windows.Forms.LinkLabel audibleLink;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -131,5 +131,12 @@ Audible ID: {Book.AudibleProductId}
|
|||||||
this.DialogResult = DialogResult.Cancel;
|
this.DialogResult = DialogResult.Cancel;
|
||||||
this.Close();
|
this.Close();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private void audibleLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||||
|
{
|
||||||
|
var locale = AudibleApi.Localization.Get(_libraryBook.Book.Locale);
|
||||||
|
var link = $"https://www.audible.{locale.TopDomain}/pd/{Book.AudibleProductId}";
|
||||||
|
Go.To.Url(link);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -79,7 +79,10 @@ namespace LibationWinForms.Dialogs
|
|||||||
Authors = new List<string> { "Arthur Conan Doyle", "Stephen Fry - introductions" },
|
Authors = new List<string> { "Arthur Conan Doyle", "Stephen Fry - introductions" },
|
||||||
Narrators = new List<string> { "Stephen Fry" },
|
Narrators = new List<string> { "Stephen Fry" },
|
||||||
SeriesName = "Sherlock Holmes",
|
SeriesName = "Sherlock Holmes",
|
||||||
SeriesNumber = "1"
|
SeriesNumber = "1",
|
||||||
|
BitRate = 128,
|
||||||
|
SampleRate = 44100,
|
||||||
|
Channels = 2
|
||||||
};
|
};
|
||||||
var chapterName = "A Flight for Life";
|
var chapterName = "A Flight for Life";
|
||||||
var chapterNumber = 4;
|
var chapterNumber = 4;
|
||||||
|
|||||||
@ -21,7 +21,7 @@ namespace FileNamingTemplateTests
|
|||||||
sb.Append('0', 300);
|
sb.Append('0', 300);
|
||||||
var longText = sb.ToString();
|
var longText = sb.ToString();
|
||||||
|
|
||||||
var expectedNew = "C:\\foo\\bar\\my꞉ book 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 [ID123456].txt";
|
var expectedNew = @"C:\foo\bar\my꞉ book 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 [ID123456].txt";
|
||||||
var f2 = NEW_GetValidFilename_FileNamingTemplate(@"C:\foo\bar", "my: book " + longText, "txt", "ID123456");
|
var f2 = NEW_GetValidFilename_FileNamingTemplate(@"C:\foo\bar", "my: book " + longText, "txt", "ID123456");
|
||||||
|
|
||||||
f2.Should().Be(expectedNew);
|
f2.Should().Be(expectedNew);
|
||||||
|
|||||||
@ -12,19 +12,30 @@ using static TemplatesTests.Shared;
|
|||||||
|
|
||||||
namespace TemplatesTests
|
namespace TemplatesTests
|
||||||
{
|
{
|
||||||
|
/////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// add general tag replacement tests to: //
|
||||||
|
// //
|
||||||
|
// getFileNamingTemplate.Tests //
|
||||||
|
// //
|
||||||
|
/////////////////////////////////////////////////
|
||||||
|
|
||||||
public static class Shared
|
public static class Shared
|
||||||
{
|
{
|
||||||
public static LibraryBookDto GetLibraryBook(string asin, string seriesName = "Sherlock Holmes")
|
public static LibraryBookDto GetLibraryBook(string seriesName = "Sherlock Holmes")
|
||||||
=> new()
|
=> new()
|
||||||
{
|
{
|
||||||
Account = "my account",
|
Account = "my account",
|
||||||
AudibleProductId = asin,
|
AudibleProductId = "asin",
|
||||||
Title = "A Study in Scarlet: A Sherlock Holmes Novel",
|
Title = "A Study in Scarlet: A Sherlock Holmes Novel",
|
||||||
Locale = "us",
|
Locale = "us",
|
||||||
Authors = new List<string> { "Arthur Conan Doyle", "Stephen Fry - introductions" },
|
Authors = new List<string> { "Arthur Conan Doyle", "Stephen Fry - introductions" },
|
||||||
Narrators = new List<string> { "Stephen Fry" },
|
Narrators = new List<string> { "Stephen Fry" },
|
||||||
SeriesName = seriesName ?? "",
|
SeriesName = seriesName ?? "",
|
||||||
SeriesNumber = "1"
|
SeriesNumber = "1",
|
||||||
|
BitRate = 128,
|
||||||
|
SampleRate = 44100,
|
||||||
|
Channels = 2
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,48 +67,49 @@ namespace TemplatesTests
|
|||||||
|
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
[DataRow(null, "asin", @"C:\", "ext")]
|
[DataRow(null, @"C:\", "ext")]
|
||||||
[ExpectedException(typeof(ArgumentNullException))]
|
[ExpectedException(typeof(ArgumentNullException))]
|
||||||
public void arg_null_exception(string template, string asin, string dirFullPath, string extension)
|
public void arg_null_exception(string template, string dirFullPath, string extension)
|
||||||
=> Templates.getFileNamingTemplate(GetLibraryBook(asin), template, dirFullPath, extension);
|
=> Templates.getFileNamingTemplate(GetLibraryBook(), template, dirFullPath, extension);
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
[DataRow("", "asin", @"C:\foo\bar", "ext")]
|
[DataRow("", @"C:\foo\bar", "ext")]
|
||||||
[DataRow(" ", "asin", @"C:\foo\bar", "ext")]
|
[DataRow(" ", @"C:\foo\bar", "ext")]
|
||||||
[ExpectedException(typeof(ArgumentException))]
|
[ExpectedException(typeof(ArgumentException))]
|
||||||
public void arg_exception(string template, string asin, string dirFullPath, string extension)
|
public void arg_exception(string template, string dirFullPath, string extension)
|
||||||
=> Templates.getFileNamingTemplate(GetLibraryBook(asin), template, dirFullPath, extension);
|
=> Templates.getFileNamingTemplate(GetLibraryBook(), template, dirFullPath, extension);
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void null_extension() => Tests("f.txt", "asin", @"C:\foo\bar", null, @"C:\foo\bar\f.txt");
|
public void null_extension() => Tests("f.txt", @"C:\foo\bar", null, @"C:\foo\bar\f.txt");
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
[DataRow("f.txt", "asin", @"C:\foo\bar", "ext", @"C:\foo\bar\f.txt.ext")]
|
[DataRow("f.txt", @"C:\foo\bar", "ext", @"C:\foo\bar\f.txt.ext")]
|
||||||
[DataRow("f", "asin", @"C:\foo\bar", "ext", @"C:\foo\bar\f.ext")]
|
[DataRow("f", @"C:\foo\bar", "ext", @"C:\foo\bar\f.ext")]
|
||||||
[DataRow("<id>", "asin", @"C:\foo\bar", "ext", @"C:\foo\bar\asin.ext")]
|
[DataRow("<id>", @"C:\foo\bar", "ext", @"C:\foo\bar\asin.ext")]
|
||||||
public void Tests(string template, string asin, string dirFullPath, string extension, string expected)
|
[DataRow("<bitrate> - <samplerate> - <channels>", @"C:\foo\bar", "ext", @"C:\foo\bar\128 - 44100 - 2.ext")]
|
||||||
=> Templates.getFileNamingTemplate(GetLibraryBook(asin), template, dirFullPath, extension)
|
public void Tests(string template, string dirFullPath, string extension, string expected)
|
||||||
|
=> Templates.getFileNamingTemplate(GetLibraryBook(), template, dirFullPath, extension)
|
||||||
.GetFilePath(Replacements)
|
.GetFilePath(Replacements)
|
||||||
.PathWithoutPrefix
|
.PathWithoutPrefix
|
||||||
.Should().Be(expected);
|
.Should().Be(expected);
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void IfSeries_empty()
|
public void IfSeries_empty()
|
||||||
=> Templates.getFileNamingTemplate(GetLibraryBook("asin", "Sherlock Holmes"), "foo<if series-><-if series>bar", @"C:\a\b", "ext")
|
=> Templates.getFileNamingTemplate(GetLibraryBook(), "foo<if series-><-if series>bar", @"C:\a\b", "ext")
|
||||||
.GetFilePath(Replacements)
|
.GetFilePath(Replacements)
|
||||||
.PathWithoutPrefix
|
.PathWithoutPrefix
|
||||||
.Should().Be(@"C:\a\b\foobar.ext");
|
.Should().Be(@"C:\a\b\foobar.ext");
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void IfSeries_no_series()
|
public void IfSeries_no_series()
|
||||||
=> Templates.getFileNamingTemplate(GetLibraryBook("asin", ""), "foo<if series->-<series>-<id>-<-if series>bar", @"C:\a\b", "ext")
|
=> Templates.getFileNamingTemplate(GetLibraryBook(null), "foo<if series->-<series>-<id>-<-if series>bar", @"C:\a\b", "ext")
|
||||||
.GetFilePath(Replacements)
|
.GetFilePath(Replacements)
|
||||||
.PathWithoutPrefix
|
.PathWithoutPrefix
|
||||||
.Should().Be(@"C:\a\b\foobar.ext");
|
.Should().Be(@"C:\a\b\foobar.ext");
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void IfSeries_with_series()
|
public void IfSeries_with_series()
|
||||||
=> Templates.getFileNamingTemplate(GetLibraryBook("asin", "Sherlock Holmes"), "foo<if series->-<series>-<id>-<-if series>bar", @"C:\a\b", "ext")
|
=> Templates.getFileNamingTemplate(GetLibraryBook(), "foo<if series->-<series>-<id>-<-if series>bar", @"C:\a\b", "ext")
|
||||||
.GetFilePath(Replacements)
|
.GetFilePath(Replacements)
|
||||||
.PathWithoutPrefix
|
.PathWithoutPrefix
|
||||||
.Should().Be(@"C:\a\b\foo-Sherlock Holmes-asin-bar.ext");
|
.Should().Be(@"C:\a\b\foo-Sherlock Holmes-asin-bar.ext");
|
||||||
@ -394,10 +406,10 @@ namespace Templates_ChapterFile_Tests
|
|||||||
static readonly ReplacementCharacters Default = ReplacementCharacters.Default;
|
static readonly ReplacementCharacters Default = ReplacementCharacters.Default;
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
[DataRow("asin", "[<id>] <ch# 0> of <ch count> - <ch title>", @"C:\foo\", "txt", 6, 10, "chap", @"C:\foo\[asin] 06 of 10 - chap.txt")]
|
[DataRow("[<id>] <ch# 0> of <ch count> - <ch title>", @"C:\foo\", "txt", 6, 10, "chap", @"C:\foo\[asin] 06 of 10 - chap.txt")]
|
||||||
[DataRow("asin", "<ch#>", @"C:\foo\", "txt", 6, 10, "chap", @"C:\foo\6.txt")]
|
[DataRow("<ch#>", @"C:\foo\", "txt", 6, 10, "chap", @"C:\foo\6.txt")]
|
||||||
public void Tests(string asin, string template, string dir, string ext, int pos, int total, string chapter, string expected)
|
public void Tests(string template, string dir, string ext, int pos, int total, string chapter, string expected)
|
||||||
=> Templates.ChapterFile.GetPortionFilename(GetLibraryBook(asin), template, new() { OutputFileName = $"xyz.{ext}", PartsPosition = pos, PartsTotal = total, Title = chapter }, dir, Default)
|
=> Templates.ChapterFile.GetPortionFilename(GetLibraryBook(), template, new() { OutputFileName = $"xyz.{ext}", PartsPosition = pos, PartsTotal = total, Title = chapter }, dir, Default)
|
||||||
.Should().Be(expected);
|
.Should().Be(expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user