From 2e4258b36100f12e0894bf2e703ed9891cc9d751 Mon Sep 17 00:00:00 2001 From: libgenapps <33476799+libgenapps@users.noreply.github.com> Date: Mon, 21 May 2018 03:34:44 +0300 Subject: [PATCH] Scan non-fiction --- LibgenDesktop.Setup/Constants.cs | 4 +- LibgenDesktop/Common/Constants.cs | 10 +- .../Infrastructure/RegisteredWindows.cs | 2 + LibgenDesktop/LibgenDesktop.csproj | 16 +++ .../Models/Database/LocalDatabase.cs | 26 ++++ LibgenDesktop/Models/Database/SqlScripts.cs | 9 ++ LibgenDesktop/Models/Localization/Language.cs | 3 + .../Localizators/LibraryWindowLocalizator.cs | 33 +++++ .../Localization/Localizators/Localizator.cs | 1 + .../Localizators/MainWindowLocalizator.cs | 2 + .../Models/Localization/Translation.cs | 13 ++ LibgenDesktop/Models/MainModel.cs | 66 ++++++++++ .../Models/ProgressArgs/GenericProgress.cs | 17 +++ .../ProgressArgs/ScanCompleteProgress.cs | 14 ++ .../Models/ProgressArgs/ScanProgress.cs | 26 ++++ LibgenDesktop/Resources/Languages/English.lng | 11 ++ LibgenDesktop/Resources/Languages/Russian.lng | 11 ++ .../Resources/Mirrors/mirrors.config | 5 + .../Windows/LibraryWindowViewModel.cs | 120 ++++++++++++++++++ .../ViewModels/Windows/MainWindowViewModel.cs | 10 ++ LibgenDesktop/Views/Controls/Toolbar.xaml | 6 + .../Styles/DownloadManagerTabStyles.xaml | 4 - .../Views/Styles/LibraryWindowStyles.xaml | 14 ++ LibgenDesktop/Views/Styles/WindowStyles.xaml | 7 + .../Views/Windows/LibraryWindow.xaml | 23 ++++ .../Views/Windows/LibraryWindow.xaml.cs | 10 ++ 26 files changed, 454 insertions(+), 9 deletions(-) create mode 100644 LibgenDesktop/Models/Localization/Localizators/LibraryWindowLocalizator.cs create mode 100644 LibgenDesktop/Models/ProgressArgs/GenericProgress.cs create mode 100644 LibgenDesktop/Models/ProgressArgs/ScanCompleteProgress.cs create mode 100644 LibgenDesktop/Models/ProgressArgs/ScanProgress.cs create mode 100644 LibgenDesktop/ViewModels/Windows/LibraryWindowViewModel.cs create mode 100644 LibgenDesktop/Views/Styles/LibraryWindowStyles.xaml create mode 100644 LibgenDesktop/Views/Windows/LibraryWindow.xaml create mode 100644 LibgenDesktop/Views/Windows/LibraryWindow.xaml.cs diff --git a/LibgenDesktop.Setup/Constants.cs b/LibgenDesktop.Setup/Constants.cs index ec606ad..3e343c9 100644 --- a/LibgenDesktop.Setup/Constants.cs +++ b/LibgenDesktop.Setup/Constants.cs @@ -2,8 +2,8 @@ { internal static class Constants { - public const string CURRENT_VERSION = "1.1.1"; - public const string TITLE_VERSION = "1.1.1"; + public const string CURRENT_VERSION = "1.1.2"; + public const string TITLE_VERSION = "1.1.2"; public const string PRODUCT_TITLE_FORMAT = "Libgen Desktop " + TITLE_VERSION + " ({0}-bit)"; public const string SHORTCUT_TITLE_FORMAT = "Libgen Desktop ({0}-bit)"; public const string PRODUCT_COMPANY = "Libgen Apps"; diff --git a/LibgenDesktop/Common/Constants.cs b/LibgenDesktop/Common/Constants.cs index b1e1952..0d4143d 100644 --- a/LibgenDesktop/Common/Constants.cs +++ b/LibgenDesktop/Common/Constants.cs @@ -4,9 +4,9 @@ namespace LibgenDesktop.Common { internal static class Constants { - public const string CURRENT_VERSION = "1.1.1"; - public const string CURRENT_GITHUB_RELEASE_NAME = "1.1.1"; - public static readonly DateTime CURRENT_GITHUB_RELEASE_DATE = new DateTime(2018, 5, 2); + public const string CURRENT_VERSION = "1.1.2"; + public const string CURRENT_GITHUB_RELEASE_NAME = "1.1.2"; + public static readonly DateTime CURRENT_GITHUB_RELEASE_DATE = new DateTime(2018, 5, 21); public const string CURRENT_DATABASE_VERSION = "1.0"; public const string APP_SETTINGS_FILE_NAME = "libgen.config"; @@ -56,6 +56,10 @@ internal static class Constants public const int IMPORT_WINDOW_MIN_WIDTH = 530; public const int IMPORT_WINDOW_MIN_HEIGHT = 400; public const int CREATE_DATABASE_WINDOW_WIDTH = 500; + public const int LIBRARY_WINDOW_DEFAULT_WIDTH = 760; + public const int LIBRARY_WINDOW_DEFAULT_HEIGHT = 550; + public const int LIBRARY_WINDOW_MIN_WIDTH = 760; + public const int LIBRARY_WINDOW_MIN_HEIGHT = 550; public const int SETTINGS_WINDOW_DEFAULT_WIDTH = 760; public const int SETTINGS_WINDOW_DEFAULT_HEIGHT = 550; public const int SETTINGS_WINDOW_MIN_WIDTH = 760; diff --git a/LibgenDesktop/Infrastructure/RegisteredWindows.cs b/LibgenDesktop/Infrastructure/RegisteredWindows.cs index 6609caa..bbf6524 100644 --- a/LibgenDesktop/Infrastructure/RegisteredWindows.cs +++ b/LibgenDesktop/Infrastructure/RegisteredWindows.cs @@ -19,6 +19,7 @@ internal enum WindowKey SETTINGS_WINDOW, SYNCHRONIZATION_WINDOW, APPLICATION_UPDATE_WINDOW, + LIBRARY_WINDOW, DATABASE_WINDOW, ABOUT_WINDOW } @@ -49,6 +50,7 @@ static RegisteredWindows() RegisterWindow(WindowKey.CREATE_DATABASE_WINDOW, typeof(CreateDatabaseWindow), typeof(CreateDatabaseWindowViewModel)); RegisterWindow(WindowKey.SETTINGS_WINDOW, typeof(SettingsWindow), typeof(SettingsWindowViewModel)); RegisterWindow(WindowKey.SYNCHRONIZATION_WINDOW, typeof(SynchronizationWindow), typeof(SynchronizationWindowViewModel)); + RegisterWindow(WindowKey.LIBRARY_WINDOW, typeof(LibraryWindow), typeof(LibraryWindowViewModel)); RegisterWindow(WindowKey.APPLICATION_UPDATE_WINDOW, typeof(ApplicationUpdateWindow), typeof(ApplicationUpdateWindowViewModel)); RegisterWindow(WindowKey.DATABASE_WINDOW, typeof(DatabaseWindow), typeof(DatabaseWindowViewModel)); RegisterWindow(WindowKey.ABOUT_WINDOW, typeof(AboutWindow), typeof(AboutWindowViewModel)); diff --git a/LibgenDesktop/LibgenDesktop.csproj b/LibgenDesktop/LibgenDesktop.csproj index 5765585..ee8468a 100644 --- a/LibgenDesktop/LibgenDesktop.csproj +++ b/LibgenDesktop/LibgenDesktop.csproj @@ -170,6 +170,7 @@ + @@ -201,12 +202,15 @@ + + + @@ -239,6 +243,7 @@ + @@ -295,6 +300,9 @@ AboutWindow.xaml + + LibraryWindow.xaml + DatabaseWindow.xaml @@ -376,6 +384,10 @@ MSBuild:Compile Designer + + MSBuild:Compile + Designer + MSBuild:Compile Designer @@ -408,6 +420,10 @@ MSBuild:Compile Designer + + MSBuild:Compile + Designer + MSBuild:Compile Designer diff --git a/LibgenDesktop/Models/Database/LocalDatabase.cs b/LibgenDesktop/Models/Database/LocalDatabase.cs index c90aef9..ce7d03f 100644 --- a/LibgenDesktop/Models/Database/LocalDatabase.cs +++ b/LibgenDesktop/Models/Database/LocalDatabase.cs @@ -133,6 +133,11 @@ public void CreateNonFictionTables() ExecuteCommands(SqlScripts.CREATE_NON_FICTION_FTS_TABLE); } + public void CreateNonFictionMd5HashIndex() + { + ExecuteCommands(SqlScripts.CREATE_NON_FICTION_MD5HASH_INDEX); + } + public void CreateNonFictionLastModifiedDateTimeIndex() { ExecuteCommands(SqlScripts.CREATE_NON_FICTION_LASTMODIFIEDDATETIME_INDEX); @@ -174,6 +179,27 @@ public NonFictionBook GetNonFictionBookById(int id) } } + public NonFictionBook GetNonFictionBookByMd5Hash(string md5Hash) + { + using (SQLiteCommand command = connection.CreateCommand()) + { + command.CommandText = SqlScripts.GET_NON_FICTION_BY_MD5HASH; + command.Parameters.AddWithValue("@Md5Hash", md5Hash); + using (SQLiteDataReader dataReader = command.ExecuteReader()) + { + if (dataReader.Read()) + { + NonFictionBook book = ReadNonFictionBook(dataReader); + return book; + } + else + { + return null; + } + } + } + } + public int? GetNonFictionBookIdByLibgenId(int libgenId) { return GetIdByLibgenId(SqlScripts.GET_NON_FICTION_ID_BY_LIBGENID, libgenId); diff --git a/LibgenDesktop/Models/Database/SqlScripts.cs b/LibgenDesktop/Models/Database/SqlScripts.cs index 289074d..41a460a 100644 --- a/LibgenDesktop/Models/Database/SqlScripts.cs +++ b/LibgenDesktop/Models/Database/SqlScripts.cs @@ -82,6 +82,8 @@ internal static class SqlScripts public const string GET_NON_FICTION_BY_ID = "SELECT * FROM non_fiction WHERE Id = @Id"; + public const string GET_NON_FICTION_BY_MD5HASH = "SELECT * FROM non_fiction WHERE Md5Hash = @Md5Hash COLLATE NOCASE"; + public const string GET_NON_FICTION_ID_BY_LIBGENID = "SELECT Id FROM non_fiction WHERE LibgenId=@LibgenId LIMIT 1"; public const string GET_LAST_MODIFIED_NON_FICTION = @@ -162,6 +164,9 @@ internal static class SqlScripts public const string NON_FICTION_INDEX_PREFIX = "IX_non_fiction_"; + public const string CREATE_NON_FICTION_MD5HASH_INDEX = "CREATE UNIQUE INDEX " + NON_FICTION_INDEX_PREFIX + + "Md5Hash ON non_fiction (Md5Hash COLLATE NOCASE)"; + public const string CREATE_NON_FICTION_LASTMODIFIEDDATETIME_INDEX = "CREATE INDEX " + NON_FICTION_INDEX_PREFIX + "LastModifiedDateTime ON non_fiction (LastModifiedDateTime DESC)"; @@ -329,6 +334,8 @@ internal static class SqlScripts public const string FICTION_INDEX_PREFIX = "IX_fiction_"; + public const string CREATE_FICTION_MD5HASH_INDEX = "CREATE UNIQUE INDEX " + FICTION_INDEX_PREFIX + "Md5Hash ON fiction (Md5Hash COLLATE NOCASE)"; + public const string CREATE_FICTION_LASTMODIFIEDDATETIME_INDEX = "CREATE INDEX " + FICTION_INDEX_PREFIX + "LastModifiedDateTime ON fiction (LastModifiedDateTime DESC)"; @@ -399,6 +406,8 @@ internal static class SqlScripts public const string SCIMAG_INDEX_PREFIX = "IX_scimag_"; + public const string CREATE_SCIMAG_MD5HASH_INDEX = "CREATE UNIQUE INDEX " + SCIMAG_INDEX_PREFIX + "Md5Hash ON scimag (Md5Hash COLLATE NOCASE)"; + public const string CREATE_SCIMAG_ADDEDDATETIME_INDEX = "CREATE INDEX " + SCIMAG_INDEX_PREFIX + "AddedDateTime ON scimag (AddedDateTime DESC)"; } } diff --git a/LibgenDesktop/Models/Localization/Language.cs b/LibgenDesktop/Models/Localization/Language.cs index f663341..210f838 100644 --- a/LibgenDesktop/Models/Localization/Language.cs +++ b/LibgenDesktop/Models/Localization/Language.cs @@ -26,6 +26,7 @@ internal class Language private SynchronizationLocalizator synchronization; private DownloadManagerLocalizator downloadManager; private ApplicationUpdateLocalizator applicationUpdate; + private LibraryWindowLocalizator library; private DatabaseWindowLocalizator database; private SettingsWindowLocalizator settings; private AboutWindowLocalizator about; @@ -127,6 +128,8 @@ public Language(List prioritizedTranslationList) public ApplicationUpdateLocalizator ApplicationUpdate => applicationUpdate ?? (applicationUpdate = new ApplicationUpdateLocalizator(translations, Formatter)); + public LibraryWindowLocalizator Library => library ?? (library = new LibraryWindowLocalizator(translations, Formatter)); + public DatabaseWindowLocalizator Database => database ?? (database = new DatabaseWindowLocalizator(translations, Formatter)); public SettingsWindowLocalizator Settings => settings ?? (settings = new SettingsWindowLocalizator(translations, Formatter)); diff --git a/LibgenDesktop/Models/Localization/Localizators/LibraryWindowLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/LibraryWindowLocalizator.cs new file mode 100644 index 0000000..2bb5f0e --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/LibraryWindowLocalizator.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators +{ + internal class LibraryWindowLocalizator : Localizator + { + public LibraryWindowLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter) + { + WindowTitle = Format(translation => translation?.WindowTitle); + Scan = Format(translation => translation?.Scan); + BrowseDirectoryDialogTitle = Format(translation => translation?.BrowseDirectoryDialogTitle); + CreatingIndexes = Format(translation => translation?.CreatingIndexes); + NotFound = Format(translation => translation?.NotFound); + } + + public string WindowTitle { get; } + public string Scan { get; } + public string BrowseDirectoryDialogTitle { get; } + public string CreatingIndexes { get; } + public string NotFound { get; } + + public string GetScanStartedString(string directory) => Format(translation => translation?.ScanStarted, new { directory }); + public string GetScanCompleteString(int found, int notFound) => Format(translation => translation?.ScanComplete, + new { found = Formatter.ToFormattedString(found), notFound = Formatter.ToFormattedString(notFound) }); + + private string Format(Func field, object templateArguments = null) + { + return Format(translation => field(translation?.Library), templateArguments); + } + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/Localizator.cs b/LibgenDesktop/Models/Localization/Localizators/Localizator.cs index f72ce4a..e2756bd 100644 --- a/LibgenDesktop/Models/Localization/Localizators/Localizator.cs +++ b/LibgenDesktop/Models/Localization/Localizators/Localizator.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Reflection; namespace LibgenDesktop.Models.Localization.Localizators diff --git a/LibgenDesktop/Models/Localization/Localizators/MainWindowLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/MainWindowLocalizator.cs index 2638d0f..784a7c6 100644 --- a/LibgenDesktop/Models/Localization/Localizators/MainWindowLocalizator.cs +++ b/LibgenDesktop/Models/Localization/Localizators/MainWindowLocalizator.cs @@ -15,6 +15,7 @@ public MainWindowLocalizator(List prioritizedTranslationList, Langu ToolbarUpdate = Format(translation => translation?.Update); ToolbarImport = Format(translation => translation?.Import); ToolbarSynchronize = Format(translation => translation?.Synchronize); + ToolbarLibrary = Format(translation => translation?.Library); ToolbarDatabase = Format(translation => translation?.Database); ToolbarSettings = Format(translation => translation?.Settings); ToolbarAbout = Format(translation => translation?.About); @@ -27,6 +28,7 @@ public MainWindowLocalizator(List prioritizedTranslationList, Langu public string ToolbarUpdate { get; } public string ToolbarImport { get; } public string ToolbarSynchronize { get; } + public string ToolbarLibrary { get; } public string ToolbarDatabase { get; } public string ToolbarSettings { get; } public string ToolbarAbout { get; } diff --git a/LibgenDesktop/Models/Localization/Translation.cs b/LibgenDesktop/Models/Localization/Translation.cs index 8768a3d..fa75097 100644 --- a/LibgenDesktop/Models/Localization/Translation.cs +++ b/LibgenDesktop/Models/Localization/Translation.cs @@ -36,6 +36,7 @@ internal class MainMenuTranslation public string Update { get; set; } public string Import { get; set; } public string Synchronize { get; set; } + public string Library { get; set; } public string Database { get; set; } public string Settings { get; set; } public string About { get; set; } @@ -543,6 +544,17 @@ internal class SynchronizationTranslation public SynchronizationLogMessagesTranslation LogMessages { get; set; } } + internal class LibraryTranslation + { + public string WindowTitle { get; set; } + public string Scan { get; set; } + public string BrowseDirectoryDialogTitle { get; set; } + public string ScanStarted { get; set; } + public string CreatingIndexes { get; set; } + public string NotFound { get; set; } + public string ScanComplete { get; set; } + } + internal class DatabaseTranslation { public string WindowTitle { get; set; } @@ -794,6 +806,7 @@ internal class ErrorWindowTranslation public SynchronizationTranslation Synchronization { get; set; } public DownloadManagerTranslation DownloadManager { get; set; } public ApplicationUpdateTranslation ApplicationUpdate { get; set; } + public LibraryTranslation Library { get; set; } public DatabaseTranslation Database { get; set; } public SettingsTranslation Settings { get; set; } public AboutTranslation About { get; set; } diff --git a/LibgenDesktop/Models/MainModel.cs b/LibgenDesktop/Models/MainModel.cs index ec0986e..54e7153 100644 --- a/LibgenDesktop/Models/MainModel.cs +++ b/LibgenDesktop/Models/MainModel.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Net; using System.Net.Http; +using System.Security.Cryptography; using System.Threading; using System.Threading.Tasks; using LibgenDesktop.Common; @@ -482,6 +483,28 @@ public Task DownloadFileAsync(string fileUrl, string destina }); } + public Task ScanAsync(string scanDirectory, IProgress progressHandler) + { + return Task.Run(() => + { + int found = 0; + int notFound = 0; + if (NonFictionBookCount > 0) + { + Logger.Debug("Retrieving the list of non-fiction table indexes."); + List nonFictionIndexes = localDatabase.GetNonFictionIndexList(); + if (!nonFictionIndexes.Contains(SqlScripts.NON_FICTION_INDEX_PREFIX + "Md5Hash")) + { + Logger.Debug("Creating an index on Md5Hash column."); + progressHandler.Report(new GenericProgress(GenericProgress.Event.SCAN_CREATING_INDEXES)); + localDatabase.CreateNonFictionMd5HashIndex(); + } + ScanDirectory(scanDirectory.ToLower(), scanDirectory, progressHandler, ref found, ref notFound); + } + progressHandler.Report(new ScanCompleteProgress(found, notFound)); + }); + } + public Task GetDatabaseStatsAsync() { return Task.Run(() => @@ -886,6 +909,49 @@ private TableType DetectImportTableType(SqlDumpReader.ParsedTableDefinition pars return TableType.UNKNOWN; } + private void ScanDirectory(string rootScanDirectory, string scanDirectory, IProgress progressHandler, ref int found, ref int notFound) + { + foreach (string filePath in Directory.EnumerateFiles(scanDirectory)) + { + string md5Hash; + try + { + using (MD5 md5 = MD5.Create()) + using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)) + { + byte[] md5HashArray = md5.ComputeHash(fileStream); + md5Hash = BitConverter.ToString(md5HashArray).Replace("-", String.Empty).ToLowerInvariant(); + } + } + catch (Exception exception) + { + Logger.Debug($"Couldn't calculate MD5 hash for the file: {filePath}"); + Logger.Exception(exception); + continue; + } + string relativeFilePath = filePath; + if (relativeFilePath.ToLower().StartsWith(rootScanDirectory)) + { + relativeFilePath = relativeFilePath.Substring(rootScanDirectory.Length + 1); + } + NonFictionBook book = localDatabase.GetNonFictionBookByMd5Hash(md5Hash); + if (book != null) + { + progressHandler.Report(new ScanProgress(relativeFilePath, book.Authors, book.Title)); + found++; + } + else + { + progressHandler.Report(new ScanProgress(relativeFilePath)); + notFound++; + } + } + foreach (string directoryPath in Directory.EnumerateDirectories(scanDirectory)) + { + ScanDirectory(rootScanDirectory, directoryPath, progressHandler, ref found, ref notFound); + } + } + private void CheckAndCreateNonFictionIndexes(IProgress progressHandler, CancellationToken cancellationToken) { Logger.Debug("Retrieving the list of non-fiction table indexes."); diff --git a/LibgenDesktop/Models/ProgressArgs/GenericProgress.cs b/LibgenDesktop/Models/ProgressArgs/GenericProgress.cs new file mode 100644 index 0000000..2df066c --- /dev/null +++ b/LibgenDesktop/Models/ProgressArgs/GenericProgress.cs @@ -0,0 +1,17 @@ +namespace LibgenDesktop.Models.ProgressArgs +{ + internal class GenericProgress + { + internal enum Event + { + SCAN_CREATING_INDEXES + } + + public GenericProgress(Event progressEvent) + { + ProgressEvent = progressEvent; + } + + public Event ProgressEvent { get; } + } +} diff --git a/LibgenDesktop/Models/ProgressArgs/ScanCompleteProgress.cs b/LibgenDesktop/Models/ProgressArgs/ScanCompleteProgress.cs new file mode 100644 index 0000000..3e63fce --- /dev/null +++ b/LibgenDesktop/Models/ProgressArgs/ScanCompleteProgress.cs @@ -0,0 +1,14 @@ +namespace LibgenDesktop.Models.ProgressArgs +{ + internal class ScanCompleteProgress + { + public ScanCompleteProgress(int found, int notFound) + { + Found = found; + NotFound = notFound; + } + + public int Found { get; } + public int NotFound { get; } + } +} diff --git a/LibgenDesktop/Models/ProgressArgs/ScanProgress.cs b/LibgenDesktop/Models/ProgressArgs/ScanProgress.cs new file mode 100644 index 0000000..15cf70f --- /dev/null +++ b/LibgenDesktop/Models/ProgressArgs/ScanProgress.cs @@ -0,0 +1,26 @@ +namespace LibgenDesktop.Models.ProgressArgs +{ + internal class ScanProgress + { + public ScanProgress(string relativeFilePath) + { + RelativeFilePath = relativeFilePath; + Found = false; + Authors = null; + Title = null; + } + + public ScanProgress(string relativeFilePath, string authors, string title) + { + RelativeFilePath = relativeFilePath; + Found = true; + Authors = authors; + Title = title; + } + + public string RelativeFilePath { get; } + public bool Found { get; } + public string Authors { get; } + public string Title { get; } + } +} diff --git a/LibgenDesktop/Resources/Languages/English.lng b/LibgenDesktop/Resources/Languages/English.lng index e1aece7..bda19e2 100644 --- a/LibgenDesktop/Resources/Languages/English.lng +++ b/LibgenDesktop/Resources/Languages/English.lng @@ -32,6 +32,7 @@ "Update": "Update...", "Import": "Import...", "Synchronize": "Synchronization...", + "Library": "Library...", "Database": "Database...", "Settings": "Settings", "About": "About" @@ -499,6 +500,16 @@ "SynchronizationError": "An error occurred during the synchronization." } }, + "Library": + { + "WindowTitle": "Local library", + "Scan": "SCAN FOR NON-FICTION BOOKS...", + "BrowseDirectoryDialogTitle": "Scan for non-fiction books in...", + "ScanStarted": "Scan started in {directory}", + "CreatingIndexes": "Please wait. Creating missing database indexes...", + "NotFound": "not found", + "ScanComplete": "Scan complete: found {found}, not found {notFound}." + }, "Database": { "WindowTitle": "Database information", diff --git a/LibgenDesktop/Resources/Languages/Russian.lng b/LibgenDesktop/Resources/Languages/Russian.lng index cad623d..4a6822c 100644 --- a/LibgenDesktop/Resources/Languages/Russian.lng +++ b/LibgenDesktop/Resources/Languages/Russian.lng @@ -32,6 +32,7 @@ "Update": "Обновление...", "Import": "Импорт...", "Synchronize": "Синхронизация...", + "Library": "Библиотека...", "Database": "База данных...", "Settings": "Настройки", "About": "О программе" @@ -499,6 +500,16 @@ "SynchronizationError": "Синхронизация завершилась с ошибками." } }, + "Library": + { + "WindowTitle": "Локальная библиотека", + "Scan": "СКАНИРОВАТЬ ПО БАЗЕ НЕХУДОЖЕСТВЕННОЙ ЛИТЕРАТУРЫ...", + "BrowseDirectoryDialogTitle": "Искать известные книги в...", + "ScanStarted": "Начато сканирование в {directory}", + "CreatingIndexes": "Идет создание отсутствующих индексов. Пожалуйста, подождите...", + "NotFound": "не найдено", + "ScanComplete": "Сканирование завершено: найдено {found}, не найдено {notFound}." + }, "Database": { "WindowTitle": "Статистика базы данных", diff --git a/LibgenDesktop/Resources/Mirrors/mirrors.config b/LibgenDesktop/Resources/Mirrors/mirrors.config index c435c43..10a371d 100644 --- a/LibgenDesktop/Resources/Mirrors/mirrors.config +++ b/LibgenDesktop/Resources/Mirrors/mirrors.config @@ -45,5 +45,10 @@ { "SciMagDownloadUrl": "http://booksc.org/s/?q={doi}&t=0", "SciMagDownloadTransformations": "booksc_org" + }, + "GenoType (TOR)": + { + "NonFictionDownloadUrl": "http://genotypeinczgrxr.onion/LG/{thousand-index}/{md5:l}", + "FictionDownloadUrl": "http://genotypeinczgrxr.onion/FF/{thousand-index}/{md5:l}.{ext}", } } \ No newline at end of file diff --git a/LibgenDesktop/ViewModels/Windows/LibraryWindowViewModel.cs b/LibgenDesktop/ViewModels/Windows/LibraryWindowViewModel.cs new file mode 100644 index 0000000..0043f72 --- /dev/null +++ b/LibgenDesktop/ViewModels/Windows/LibraryWindowViewModel.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.ObjectModel; +using LibgenDesktop.Infrastructure; +using LibgenDesktop.Models; +using LibgenDesktop.Models.Localization.Localizators; +using LibgenDesktop.Models.ProgressArgs; + +namespace LibgenDesktop.ViewModels.Windows +{ + internal class LibraryWindowViewModel : LibgenWindowViewModel + { + private bool isScanButtonVisible; + private bool isLogPanelVisible; + private ObservableCollection scanLogs; + + public LibraryWindowViewModel(MainModel mainModel) + : base(mainModel) + { + Localization = mainModel.Localization.CurrentLanguage.Library; + ScanCommand = new Command(Scan); + Initialize(); + } + + public LibraryWindowLocalizator Localization { get; } + + public bool IsScanButtonVisible + { + get + { + return isScanButtonVisible; + } + set + { + isScanButtonVisible = value; + NotifyPropertyChanged(); + } + } + + public bool IsLogPanelVisible + { + get + { + return isLogPanelVisible; + } + set + { + isLogPanelVisible = value; + NotifyPropertyChanged(); + } + } + + public ObservableCollection ScanLogs + { + get + { + return scanLogs; + } + set + { + scanLogs = value; + NotifyPropertyChanged(); + } + } + + public Command ScanCommand { get; } + + private void Initialize() + { + isScanButtonVisible = true; + isLogPanelVisible = false; + scanLogs = new ObservableCollection(); + } + + private async void Scan() + { + SelectFolderDialogParameters selectFolderDialogParameters = new SelectFolderDialogParameters + { + DialogTitle = Localization.BrowseDirectoryDialogTitle + }; + SelectFolderDialogResult selectFolderDialogResult = WindowManager.ShowSelectFolderDialog(selectFolderDialogParameters); + if (selectFolderDialogResult.DialogResult) + { + IsScanButtonVisible = false; + IsLogPanelVisible = true; + string scanDirectory = selectFolderDialogResult.SelectedFolderPath; + ScanLogs.Add(Localization.GetScanStartedString(scanDirectory)); + Progress scanProgressHandler = new Progress(HandleScanProgress); + await MainModel.ScanAsync(scanDirectory, scanProgressHandler); + } + } + + private void HandleScanProgress(object progress) + { + switch (progress) + { + case GenericProgress genericProgress: + switch (genericProgress.ProgressEvent) + { + case GenericProgress.Event.SCAN_CREATING_INDEXES: + ScanLogs.Add(Localization.CreatingIndexes); + break; + } + break; + case ScanProgress scanProgress: + if (scanProgress.Found) + { + ScanLogs.Add($"{scanProgress.RelativeFilePath}: {scanProgress.Authors} — {scanProgress.Title}"); + } + else + { + ScanLogs.Add($"{scanProgress.RelativeFilePath}: {Localization.NotFound}."); + } + break; + case ScanCompleteProgress scanCompleteProgress: + ScanLogs.Add(Localization.GetScanCompleteString(scanCompleteProgress.Found, scanCompleteProgress.NotFound)); + break; + } + } + } +} diff --git a/LibgenDesktop/ViewModels/Windows/MainWindowViewModel.cs b/LibgenDesktop/ViewModels/Windows/MainWindowViewModel.cs index 6fc8703..157aef7 100644 --- a/LibgenDesktop/ViewModels/Windows/MainWindowViewModel.cs +++ b/LibgenDesktop/ViewModels/Windows/MainWindowViewModel.cs @@ -42,6 +42,7 @@ public MainWindowViewModel(MainModel mainModel) ShowApplicationUpdateCommand = new Command(ShowApplicationUpdate); ImportCommand = new Command(Import); SynchronizeCommand = new Command(Synchronize); + LibraryCommand = new Command(LibraryMenuItemClick); DatabaseCommand = new Command(DatabaseMenuItemClick); BookmarkCommand = new Command(param => BookmarksMenuItemClick(param as BookmarkViewModel)); SettingsCommand = new Command(SettingsMenuItemClick); @@ -199,6 +200,7 @@ public BookmarkViewModelList Bookmarks public Command ShowApplicationUpdateCommand { get; } public Command ImportCommand { get; } public Command SynchronizeCommand { get; } + public Command LibraryCommand { get; } public Command DatabaseCommand { get; } public Command BookmarkCommand { get; } public Command SettingsCommand { get; } @@ -630,6 +632,14 @@ public void Synchronize() } } + private void LibraryMenuItemClick() + { + LibraryWindowViewModel libraryWindowViewModel = new LibraryWindowViewModel(MainModel); + IWindowContext libraryWindowContext = WindowManager.CreateWindow(RegisteredWindows.WindowKey.LIBRARY_WINDOW, libraryWindowViewModel, + CurrentWindowContext); + libraryWindowContext.ShowDialog(); + } + private void DatabaseMenuItemClick() { DatabaseWindowViewModel databaseWindowViewModel = new DatabaseWindowViewModel(MainModel); diff --git a/LibgenDesktop/Views/Controls/Toolbar.xaml b/LibgenDesktop/Views/Controls/Toolbar.xaml index 96ead16..8c8e649 100644 --- a/LibgenDesktop/Views/Controls/Toolbar.xaml +++ b/LibgenDesktop/Views/Controls/Toolbar.xaml @@ -85,6 +85,12 @@ +