|
9 | 9 | using System.Threading; |
10 | 10 | using System.Windows.Forms; |
11 | 11 | using Bloom.Api; |
| 12 | +using Bloom.Collection; |
12 | 13 | using Bloom.Edit; |
13 | 14 | using Bloom.Utils; |
14 | 15 | using L10NSharp; |
@@ -341,6 +342,8 @@ public string Copyright |
341 | 342 | /// </summary> |
342 | 343 | public string QuickTitleUserDisplay => FolderName; |
343 | 344 |
|
| 345 | + public string ThumbnailLabel; |
| 346 | + |
344 | 347 | public bool TryGetPremadeThumbnail(out Image image) |
345 | 348 | { |
346 | 349 | string path = Path.Combine(FolderPath, "thumbnail.png"); |
@@ -851,29 +854,104 @@ internal string GetBestTitleForUserDisplay( |
851 | 854 | List<string> langCodes, |
852 | 855 | bool ignoreFolderName = false |
853 | 856 | ) |
| 857 | + { |
| 858 | + return GetBestDisplayTitle(null, null, langCodes, ignoreFolderName); |
| 859 | + } |
| 860 | + |
| 861 | + internal string GetBestDisplayTitle( |
| 862 | + CollectionSettings settings, // may be null |
| 863 | + Book book, // may be null, but if we have it, we can use it to get the title without having to read the html again |
| 864 | + List<string> langCodes = null, |
| 865 | + bool ignoreFolderName = false |
| 866 | + ) |
854 | 867 | { |
855 | 868 | if (!ignoreFolderName && FileNameLocked) |
856 | | - return FolderName; |
857 | | - try |
858 | 869 | { |
859 | | - // JSON parsing requires newlines to be double quoted with backslashes inside string values. |
860 | | - var jsonString = |
861 | | - AllTitles == null ? "{}" : AllTitles.Replace("\r", "\\r").Replace("\n", "\\n"); |
862 | | - dynamic titles = DynamicJson.Parse(jsonString); |
863 | | - IEnumerable<string> langs = titles.GetDynamicMemberNames(); |
864 | | - var multiText = new MultiTextBase(); |
865 | | - // I have no idea why "item" gets included...it's never a language id, so never in the json... |
866 | | - // but sometimes it does, and then titles["item"] throws, and this method does not |
867 | | - // behave as expected. |
868 | | - foreach (var lang in langs.Where((l) => l != "item")) |
869 | | - multiText[lang] = titles[lang].Trim(); |
870 | | - return Book.GetBestTitleForDisplay(multiText, langCodes, IsInEditableCollection); |
| 870 | + // The user has explicitly chosen a name to use for the book, distinct from its titles. |
| 871 | + return FolderName; |
871 | 872 | } |
872 | | - catch (Exception e) |
| 873 | + if (String.IsNullOrEmpty(Title)) |
873 | 874 | { |
874 | | - Console.WriteLine(e); |
| 875 | + if (IsInEditableCollection) |
| 876 | + { |
| 877 | + // If we have the book, we can use that for getting the title. |
| 878 | + // If we have the settings but not the book, we can use the settings to get the title from the html. |
| 879 | + if (!string.IsNullOrEmpty(FolderPath) && (book != null || settings != null)) |
| 880 | + { |
| 881 | + // Use the loaded book if we have it to get the best title. |
| 882 | + if ( |
| 883 | + FolderPath == book?.FolderPath |
| 884 | + && book.BookInfo.SaveContext == SaveContext |
| 885 | + ) |
| 886 | + { |
| 887 | + if (langCodes == null) |
| 888 | + langCodes = book.BookData.GetBasicBookLanguageCodes().ToList(); |
| 889 | + var best = Book.GetBestTitleForDisplay( |
| 890 | + book.BookData.GetMultiTextVariableOrEmpty("bookTitle"), |
| 891 | + langCodes, |
| 892 | + IsInEditableCollection |
| 893 | + ); |
| 894 | + if (!string.IsNullOrEmpty(best)) |
| 895 | + return best; |
| 896 | + } |
| 897 | + else |
| 898 | + { |
| 899 | + // If we can create a BookData, we can get the title from there. |
| 900 | + var htmlPath = BookStorage.FindBookHtmlInFolder(FolderPath); |
| 901 | + if ( |
| 902 | + !string.IsNullOrEmpty(htmlPath) |
| 903 | + && RobustFile.Exists(htmlPath) |
| 904 | + && settings != null |
| 905 | + ) |
| 906 | + { |
| 907 | + var dom = HtmlDom.CreateFromHtmlFile(htmlPath); |
| 908 | + var bookData = new BookData(dom, settings, null); |
| 909 | + if (langCodes == null) |
| 910 | + langCodes = bookData.GetBasicBookLanguageCodes().ToList(); |
| 911 | + var best = Book.GetBestTitleForDisplay( |
| 912 | + bookData.GetMultiTextVariableOrEmpty("bookTitle"), |
| 913 | + langCodes, |
| 914 | + IsInEditableCollection |
| 915 | + ); |
| 916 | + if (!string.IsNullOrEmpty(best)) |
| 917 | + return best; |
| 918 | + } |
| 919 | + } |
| 920 | + } |
| 921 | + } |
| 922 | + // If we still don't have a title, try to get one from the metadata. |
| 923 | + // This code is used for all books that are not in the editable collection, and for any books |
| 924 | + // in the editable collection that don't seem to have any title in the HTML. (The latter case |
| 925 | + // may be hopeless, but this check isn't very expensive.) |
| 926 | + try |
| 927 | + { |
| 928 | + // JSON parsing requires newlines to be double quoted with backslashes inside string values. |
| 929 | + var jsonString = |
| 930 | + AllTitles == null |
| 931 | + ? "{}" |
| 932 | + : AllTitles.Replace("\r", "\\r").Replace("\n", "\\n"); |
| 933 | + dynamic titles = DynamicJson.Parse(jsonString); |
| 934 | + IEnumerable<string> langs = titles.GetDynamicMemberNames(); |
| 935 | + var multiText = new MultiTextBase(); |
| 936 | + // I have no idea why "item" gets included...it's never a language id, so never in the json... |
| 937 | + // but sometimes it does, and then titles["item"] throws, and this method does not |
| 938 | + // behave as expected. |
| 939 | + foreach (var lang in langs.Where((l) => l != "item")) |
| 940 | + multiText[lang] = titles[lang].Trim(); |
| 941 | + if (langCodes == null) |
| 942 | + langCodes = langs.Where((l) => l != "item").ToList(); |
| 943 | + return Book.GetBestTitleForDisplay( |
| 944 | + multiText, |
| 945 | + langCodes, |
| 946 | + IsInEditableCollection |
| 947 | + ); |
| 948 | + } |
| 949 | + catch (Exception e) |
| 950 | + { |
| 951 | + Console.WriteLine(e); |
| 952 | + } |
875 | 953 | } |
876 | | - return Title; |
| 954 | + return Title; // Title may be empty, but we have no better option at this point. |
877 | 955 | } |
878 | 956 |
|
879 | 957 | private static void SafelyAddToIdSet( |
|
0 commit comments