diff --git a/LibgenDesktop.Setup/Constants.cs b/LibgenDesktop.Setup/Constants.cs index e39a086..7e3c062 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.4"; - public const string TITLE_VERSION = "1.1.4"; + public const string CURRENT_VERSION = "1.1.5"; + public const string TITLE_VERSION = "1.1.5"; 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 f34d362..219c946 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.4"; - public const string CURRENT_GITHUB_RELEASE_NAME = "1.1.4"; - public static readonly DateTime CURRENT_GITHUB_RELEASE_DATE = new DateTime(2018, 5, 23); + public const string CURRENT_VERSION = "1.1.5"; + public const string CURRENT_GITHUB_RELEASE_NAME = "1.1.5"; + public static readonly DateTime CURRENT_GITHUB_RELEASE_DATE = new DateTime(2018, 5, 24); public const string CURRENT_DATABASE_VERSION = "1.0"; public const string APP_SETTINGS_FILE_NAME = "libgen.config"; diff --git a/LibgenDesktop/Infrastructure/RegisteredWindows.cs b/LibgenDesktop/Infrastructure/RegisteredWindows.cs index bbf6524..ff08154 100644 --- a/LibgenDesktop/Infrastructure/RegisteredWindows.cs +++ b/LibgenDesktop/Infrastructure/RegisteredWindows.cs @@ -50,7 +50,6 @@ 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 545e133..e41fb88 100644 --- a/LibgenDesktop/LibgenDesktop.csproj +++ b/LibgenDesktop/LibgenDesktop.csproj @@ -170,7 +170,7 @@ - + @@ -244,7 +244,7 @@ - + @@ -301,8 +301,8 @@ AboutWindow.xaml - - LibraryWindow.xaml + + LibraryTab.xaml DatabaseWindow.xaml @@ -385,7 +385,7 @@ MSBuild:Compile Designer - + MSBuild:Compile Designer @@ -421,7 +421,7 @@ MSBuild:Compile Designer - + MSBuild:Compile Designer diff --git a/LibgenDesktop/Models/Localization/Language.cs b/LibgenDesktop/Models/Localization/Language.cs index 210f838..f6763f4 100644 --- a/LibgenDesktop/Models/Localization/Language.cs +++ b/LibgenDesktop/Models/Localization/Language.cs @@ -26,7 +26,7 @@ internal class Language private SynchronizationLocalizator synchronization; private DownloadManagerLocalizator downloadManager; private ApplicationUpdateLocalizator applicationUpdate; - private LibraryWindowLocalizator library; + private LibraryTabLocalizator library; private DatabaseWindowLocalizator database; private SettingsWindowLocalizator settings; private AboutWindowLocalizator about; @@ -128,7 +128,7 @@ public Language(List prioritizedTranslationList) public ApplicationUpdateLocalizator ApplicationUpdate => applicationUpdate ?? (applicationUpdate = new ApplicationUpdateLocalizator(translations, Formatter)); - public LibraryWindowLocalizator Library => library ?? (library = new LibraryWindowLocalizator(translations, Formatter)); + public LibraryTabLocalizator Library => library ?? (library = new LibraryTabLocalizator(translations, Formatter)); public DatabaseWindowLocalizator Database => database ?? (database = new DatabaseWindowLocalizator(translations, Formatter)); diff --git a/LibgenDesktop/Models/Localization/Localizators/LibraryTabLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/LibraryTabLocalizator.cs new file mode 100644 index 0000000..a1fb9e0 --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/LibraryTabLocalizator.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators +{ + internal class LibraryTabLocalizator : Localizator + { + public LibraryTabLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter) + { + TabTitle = Format(translation => translation?.TabTitle); + Scan = Format(translation => translation?.Scan); + BrowseDirectoryDialogTitle = Format(translation => translation?.BrowseDirectoryDialogTitle); + CreatingIndexes = Format(translation => translation?.CreatingIndexes); + ScanLog = Format(translation => translation?.ScanLog); + Error = Format(translation => translation?.Error); + ColumnsFile = Format(translation => translation?.File); + ColumnsAuthors = Format(translation => translation?.Authors); + ColumnsTitle = Format(translation => translation?.Title); + } + + public string TabTitle { get; } + public string Scan { get; } + public string BrowseDirectoryDialogTitle { get; } + public string CreatingIndexes { get; } + public string ScanLog { get; } + public string Error { get; } + public string ColumnsFile { get; } + public string ColumnsAuthors { get; } + public string ColumnsTitle { get; } + + public string GetScanStartedString(string directory) => Format(translation => translation?.ScanStarted, new { directory }); + public string GetFoundString(int count) => Format(translation => translation?.Found, new { count }); + public string GetNotFoundString(int count) => Format(translation => translation?.NotFound, new { count }); + public string GetScanCompleteString(int found, int notFound, int errors) => Format(translation => translation?.ScanComplete, + new { found = Formatter.ToFormattedString(found), notFound = Formatter.ToFormattedString(notFound), + errors = Formatter.ToFormattedString(errors) }); + + private string Format(Func field, object templateArguments = null) + { + return Format(translation => field(translation?.Library), templateArguments); + } + + private string Format(Func field, object templateArguments = null) + { + return Format(translation => field(translation?.Library?.Columns), templateArguments); + } + } +} diff --git a/LibgenDesktop/Models/Localization/Translation.cs b/LibgenDesktop/Models/Localization/Translation.cs index b5106cc..d75b52d 100644 --- a/LibgenDesktop/Models/Localization/Translation.cs +++ b/LibgenDesktop/Models/Localization/Translation.cs @@ -553,7 +553,7 @@ internal class LibraryColumnsTranslation internal class LibraryTranslation { - public string WindowTitle { get; set; } + public string TabTitle { get; set; } public string Scan { get; set; } public string BrowseDirectoryDialogTitle { get; set; } public string ScanStarted { get; set; } diff --git a/LibgenDesktop/Models/MainModel.cs b/LibgenDesktop/Models/MainModel.cs index 8c82038..bfe8750 100644 --- a/LibgenDesktop/Models/MainModel.cs +++ b/LibgenDesktop/Models/MainModel.cs @@ -945,7 +945,7 @@ private void ScanDirectory(string rootScanDirectory, string scanDirectory, IProg NonFictionBook book = localDatabase.GetNonFictionBookByMd5Hash(md5Hash); if (book != null) { - progressHandler.Report(new ScanProgress(relativeFilePath, book.Authors, book.Title)); + progressHandler.Report(new ScanProgress(relativeFilePath, book.Authors, book.Title, book)); found++; } else diff --git a/LibgenDesktop/Models/ProgressArgs/ScanProgress.cs b/LibgenDesktop/Models/ProgressArgs/ScanProgress.cs index 3a7edac..f7c3e83 100644 --- a/LibgenDesktop/Models/ProgressArgs/ScanProgress.cs +++ b/LibgenDesktop/Models/ProgressArgs/ScanProgress.cs @@ -1,4 +1,6 @@ -namespace LibgenDesktop.Models.ProgressArgs +using LibgenDesktop.Models.Entities; + +namespace LibgenDesktop.Models.ProgressArgs { internal class ScanProgress { @@ -9,15 +11,17 @@ public ScanProgress(string relativeFilePath, bool error = false) Error = error; Authors = null; Title = null; + LibgenObject = null; } - public ScanProgress(string relativeFilePath, string authors, string title) + public ScanProgress(string relativeFilePath, string authors, string title, NonFictionBook libgenObject) { RelativeFilePath = relativeFilePath; Found = true; Error = false; Authors = authors; Title = title; + LibgenObject = libgenObject; } public string RelativeFilePath { get; } @@ -25,5 +29,6 @@ public ScanProgress(string relativeFilePath, string authors, string title) public bool Error { get; } public string Authors { get; } public string Title { get; } + public NonFictionBook LibgenObject { get; } } } diff --git a/LibgenDesktop/Resources/Languages/English.lng b/LibgenDesktop/Resources/Languages/English.lng index a41bdae..74c3e1b 100644 --- a/LibgenDesktop/Resources/Languages/English.lng +++ b/LibgenDesktop/Resources/Languages/English.lng @@ -32,7 +32,7 @@ "Update": "Update...", "Import": "Import...", "Synchronize": "Synchronization...", - "Library": "Library...", + "Library": "Library", "Database": "Database...", "Settings": "Settings", "About": "About" @@ -502,7 +502,7 @@ }, "Library": { - "WindowTitle": "Local library", + "TabTitle": "Library", "Scan": "SCAN FOR NON-FICTION BOOKS...", "BrowseDirectoryDialogTitle": "Scan for non-fiction books in...", "ScanStarted": "Scan started in {directory}", diff --git a/LibgenDesktop/Resources/Languages/Russian.lng b/LibgenDesktop/Resources/Languages/Russian.lng index e103c97..dd72435 100644 --- a/LibgenDesktop/Resources/Languages/Russian.lng +++ b/LibgenDesktop/Resources/Languages/Russian.lng @@ -32,7 +32,7 @@ "Update": "Обновление...", "Import": "Импорт...", "Synchronize": "Синхронизация...", - "Library": "Библиотека...", + "Library": "Библиотека", "Database": "База данных...", "Settings": "Настройки", "About": "О программе" @@ -502,7 +502,7 @@ }, "Library": { - "WindowTitle": "Локальная библиотека", + "TabTitle": "Библиотека", "Scan": "СКАНИРОВАТЬ ПО БАЗЕ НЕХУДОЖЕСТВЕННОЙ ЛИТЕРАТУРЫ...", "BrowseDirectoryDialogTitle": "Искать известные книги в...", "ScanStarted": "Начато сканирование в {directory}", diff --git a/LibgenDesktop/ViewModels/Library/ScanResultItemViewModel.cs b/LibgenDesktop/ViewModels/Library/ScanResultItemViewModel.cs index bf1f8d1..4cd1c0f 100644 --- a/LibgenDesktop/ViewModels/Library/ScanResultItemViewModel.cs +++ b/LibgenDesktop/ViewModels/Library/ScanResultItemViewModel.cs @@ -5,7 +5,7 @@ namespace LibgenDesktop.ViewModels.Library internal class ScanResultItemViewModel : ViewModel { public ScanResultItemViewModel(LibgenObjectType libgenObjectType, int libgenObjectId, string fullFilePath, string relativeFilePath, string authors, - string title) + string title, NonFictionBook libgenObject) { LibgenObjectType = libgenObjectType; LibgenObjectId = libgenObjectId; @@ -13,6 +13,7 @@ public ScanResultItemViewModel(LibgenObjectType libgenObjectType, int libgenObje RelativeFilePath = relativeFilePath; Authors = authors; Title = title; + LibgenObject = libgenObject; } public LibgenObjectType LibgenObjectType { get; } @@ -21,5 +22,6 @@ public ScanResultItemViewModel(LibgenObjectType libgenObjectType, int libgenObje public string RelativeFilePath { get; } public string Authors { get; } public string Title { get; } + public NonFictionBook LibgenObject { get; } } } diff --git a/LibgenDesktop/ViewModels/Tabs/LibraryTabViewModel.cs b/LibgenDesktop/ViewModels/Tabs/LibraryTabViewModel.cs new file mode 100644 index 0000000..4a01ee1 --- /dev/null +++ b/LibgenDesktop/ViewModels/Tabs/LibraryTabViewModel.cs @@ -0,0 +1,266 @@ +using System; +using System.Collections.ObjectModel; +using LibgenDesktop.Infrastructure; +using LibgenDesktop.Models; +using LibgenDesktop.Models.Entities; +using LibgenDesktop.Models.Localization.Localizators; +using LibgenDesktop.Models.ProgressArgs; +using LibgenDesktop.ViewModels.EventArguments; +using LibgenDesktop.ViewModels.Library; + +namespace LibgenDesktop.ViewModels.Tabs +{ + internal class LibraryTabViewModel : TabViewModel + { + private LibraryTabLocalizator localization; + private bool isScanButtonVisible; + private bool isResultsPanelVisible; + private string foundTabHeaderTitle; + private string notFoundTabHeaderTitle; + private bool isScanLogTabSelected; + private ObservableCollection foundItems; + private ScanResultItemViewModel selectedFoundItem; + private ObservableCollection notFoundItems; + private ObservableCollection scanLogs; + + public LibraryTabViewModel(MainModel mainModel, IWindowContext parentWindowContext) + : base(mainModel, parentWindowContext, mainModel.Localization.CurrentLanguage.Library.TabTitle) + { + Localization = mainModel.Localization.CurrentLanguage.Library; + ScanCommand = new Command(Scan); + OpenDetailsCommand = new Command(param => OpenDetails((param as ScanResultItemViewModel))); + FoundDataGridEnterKeyCommand = new Command(FoundDataGridEnterKeyPressed); + Initialize(); + mainModel.Localization.LanguageChanged += LocalizationLanguageChanged; + } + + public LibraryTabLocalizator Localization + { + get + { + return localization; + } + set + { + localization = value; + NotifyPropertyChanged(); + } + } + + public bool IsScanButtonVisible + { + get + { + return isScanButtonVisible; + } + set + { + isScanButtonVisible = value; + NotifyPropertyChanged(); + } + } + + public bool IsResultsPanelVisible + { + get + { + return isResultsPanelVisible; + } + set + { + isResultsPanelVisible = value; + NotifyPropertyChanged(); + } + } + + public string FoundTabHeaderTitle + { + get + { + return foundTabHeaderTitle; + } + set + { + foundTabHeaderTitle = value; + NotifyPropertyChanged(); + } + } + + public string NotFoundTabHeaderTitle + { + get + { + return notFoundTabHeaderTitle; + } + set + { + notFoundTabHeaderTitle = value; + NotifyPropertyChanged(); + } + } + + public bool IsScanLogTabSelected + { + get + { + return isScanLogTabSelected; + } + set + { + isScanLogTabSelected = value; + NotifyPropertyChanged(); + } + } + + public ObservableCollection FoundItems + { + get + { + return foundItems; + } + set + { + foundItems = value; + NotifyPropertyChanged(); + } + } + + public ScanResultItemViewModel SelectedFoundItem + { + get + { + return selectedFoundItem; + } + set + { + selectedFoundItem = value; + NotifyPropertyChanged(); + } + } + + public ObservableCollection NotFoundItems + { + get + { + return notFoundItems; + } + set + { + notFoundItems = value; + NotifyPropertyChanged(); + } + } + + public ObservableCollection ScanLogs + { + get + { + return scanLogs; + } + set + { + scanLogs = value; + NotifyPropertyChanged(); + } + } + + public Command ScanCommand { get; } + public Command OpenDetailsCommand { get; } + public Command FoundDataGridEnterKeyCommand { get; } + + public event EventHandler OpenNonFictionDetailsRequested; + + private void Initialize() + { + isScanButtonVisible = true; + isResultsPanelVisible = false; + isScanLogTabSelected = false; + scanLogs = new ObservableCollection(); + } + + private async void Scan() + { + SelectFolderDialogParameters selectFolderDialogParameters = new SelectFolderDialogParameters + { + DialogTitle = Localization.BrowseDirectoryDialogTitle + }; + SelectFolderDialogResult selectFolderDialogResult = WindowManager.ShowSelectFolderDialog(selectFolderDialogParameters); + if (selectFolderDialogResult.DialogResult) + { + FoundItems = new ObservableCollection(); + NotFoundItems = new ObservableCollection(); + UpdateResultTabHeaders(); + IsScanLogTabSelected = true; + IsScanButtonVisible = false; + IsResultsPanelVisible = 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.Error) + { + ScanLogs.Add($"{scanProgress.RelativeFilePath} — {Localization.Error}."); + } + else if (scanProgress.Found) + { + FoundItems.Add(new ScanResultItemViewModel(LibgenObjectType.NON_FICTION_BOOK, 0, null, scanProgress.RelativeFilePath, + scanProgress.Authors, scanProgress.Title, scanProgress.LibgenObject)); + } + else + { + NotFoundItems.Add(scanProgress.RelativeFilePath); + } + UpdateResultTabHeaders(); + break; + case ScanCompleteProgress scanCompleteProgress: + ScanLogs.Add(Localization.GetScanCompleteString(scanCompleteProgress.Found, scanCompleteProgress.NotFound, scanCompleteProgress.Errors)); + break; + } + } + + private void UpdateResultTabHeaders() + { + if (FoundItems != null) + { + FoundTabHeaderTitle = Localization.GetFoundString(FoundItems.Count); + } + if (NotFoundItems != null) + { + NotFoundTabHeaderTitle = Localization.GetNotFoundString(NotFoundItems.Count); + } + } + + private void FoundDataGridEnterKeyPressed() + { + OpenDetails(SelectedFoundItem); + } + + private void OpenDetails(ScanResultItemViewModel foundItem) + { + OpenNonFictionDetailsRequested?.Invoke(this, new OpenNonFictionDetailsEventArgs(foundItem.LibgenObject)); + } + + private void LocalizationLanguageChanged(object sender, EventArgs e) + { + Localization = MainModel.Localization.CurrentLanguage.Library; + Title = Localization.TabTitle; + UpdateResultTabHeaders(); + } + } +} diff --git a/LibgenDesktop/ViewModels/Windows/MainWindowViewModel.cs b/LibgenDesktop/ViewModels/Windows/MainWindowViewModel.cs index 157aef7..46e0eda 100644 --- a/LibgenDesktop/ViewModels/Windows/MainWindowViewModel.cs +++ b/LibgenDesktop/ViewModels/Windows/MainWindowViewModel.cs @@ -215,6 +215,14 @@ private DownloadManagerTabViewModel DownloadManagerTabViewModel } } + private LibraryTabViewModel LibraryTabViewModel + { + get + { + return TabViewModels.OfType().FirstOrDefault(); + } + } + private void Initialize() { localization = MainModel.Localization.CurrentLanguage.MainWindow; @@ -498,6 +506,9 @@ private void CloseTab(TabViewModel tabViewModel) sciMagDetailsTabViewModel.SelectDownloadRequested -= SelectDownloadRequested; sciMagDetailsTabViewModel.CloseTabRequested -= SciMagDetailsCloseTabRequested; break; + case LibraryTabViewModel libraryTabViewModel: + libraryTabViewModel.OpenNonFictionDetailsRequested -= OpenNonFictionDetailsRequested; + break; } int removingTabIndex = TabViewModels.IndexOf(tabViewModel); TabViewModels.Remove(tabViewModel); @@ -634,10 +645,21 @@ public void Synchronize() private void LibraryMenuItemClick() { - LibraryWindowViewModel libraryWindowViewModel = new LibraryWindowViewModel(MainModel); - IWindowContext libraryWindowContext = WindowManager.CreateWindow(RegisteredWindows.WindowKey.LIBRARY_WINDOW, libraryWindowViewModel, - CurrentWindowContext); - libraryWindowContext.ShowDialog(); + LibraryTabViewModel libraryTabViewModel = LibraryTabViewModel; + if (libraryTabViewModel == null) + { + libraryTabViewModel = new LibraryTabViewModel(MainModel, CurrentWindowContext); + libraryTabViewModel.OpenNonFictionDetailsRequested += OpenNonFictionDetailsRequested; + TabViewModels.Add(libraryTabViewModel); + SelectedTabViewModel = libraryTabViewModel; + NotifyPropertyChanged(nameof(IsDefaultSearchTabVisible)); + NotifyPropertyChanged(nameof(AreTabsVisible)); + NotifyPropertyChanged(nameof(IsNewTabButtonVisible)); + } + else + { + SelectedTabViewModel = libraryTabViewModel; + } } private void DatabaseMenuItemClick() diff --git a/LibgenDesktop/Views/Styles/LibraryTabStyles.xaml b/LibgenDesktop/Views/Styles/LibraryTabStyles.xaml new file mode 100644 index 0000000..5023a5b --- /dev/null +++ b/LibgenDesktop/Views/Styles/LibraryTabStyles.xaml @@ -0,0 +1,16 @@ + + + + + + + \ No newline at end of file diff --git a/LibgenDesktop/Views/Styles/WindowStyles.xaml b/LibgenDesktop/Views/Styles/WindowStyles.xaml index 86eb1d9..5af3308 100644 --- a/LibgenDesktop/Views/Styles/WindowStyles.xaml +++ b/LibgenDesktop/Views/Styles/WindowStyles.xaml @@ -87,13 +87,6 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/LibgenDesktop/Views/Tabs/LibraryTab.xaml.cs b/LibgenDesktop/Views/Tabs/LibraryTab.xaml.cs new file mode 100644 index 0000000..37a2ac1 --- /dev/null +++ b/LibgenDesktop/Views/Tabs/LibraryTab.xaml.cs @@ -0,0 +1,10 @@ +namespace LibgenDesktop.Views.Tabs +{ + public partial class LibraryTab + { + public LibraryTab() + { + InitializeComponent(); + } + } +} diff --git a/LibgenDesktop/Views/Windows/MainWindow.xaml b/LibgenDesktop/Views/Windows/MainWindow.xaml index a5d148b..2814293 100644 --- a/LibgenDesktop/Views/Windows/MainWindow.xaml +++ b/LibgenDesktop/Views/Windows/MainWindow.xaml @@ -58,6 +58,9 @@ + + +