public SourceCollectionsList(Book.Book.Factory bookFactory, BookStorage.Factory storageFactory, BookCollection.Factory bookCollectionFactory, string editableCollectionDirectory)
 {
     _bookFactory = bookFactory;
     _storageFactory = storageFactory;
     _bookCollectionFactory = bookCollectionFactory;
     _editableCollectionDirectory = editableCollectionDirectory;
 }
Example #2
0
        public BookServer(Book.Factory bookFactory, BookStorage.Factory storageFactory,
						  BookStarter.Factory bookStarterFactory)
        {
            _bookFactory = bookFactory;
            _storageFactory = storageFactory;
            _bookStarterFactory = bookStarterFactory;
        }
        public void BringBookUpToDate_ConvertsTagsToJsonWithExpectedDefaults()
        {
            var    storage = GetInitialStorage();
            var    locator = (FileLocator)storage.GetFileLocator();
            string root    = FileLocator.GetDirectoryDistributedWithApplication(BloomFileLocator.BrowserRoot);

            locator.AddPath(root.CombineForPath("bookLayout"));
            var folder   = storage.FolderPath;
            var tagsPath = Path.Combine(folder, "tags.txt");

            File.WriteAllText(tagsPath, "suitableForMakingShells\nexperimental\nfolio\n");
            var collectionSettings =
                new CollectionSettings(new NewCollectionSettings()
            {
                PathToSettingsFile  = CollectionSettings.GetPathForNewSettings(folder, "test"),
                Language1Iso639Code = "xyz",
                Language2Iso639Code = "en",
                Language3Iso639Code = "fr"
            });
            var book = new Bloom.Book.Book(new BookInfo(folder, true), storage, new Mock <ITemplateFinder>().Object,
                                           collectionSettings,
                                           new Mock <PageSelection>().Object, new PageListChangedEvent(), new BookRefreshEvent());

            book.BringBookUpToDate(new NullProgress());

            Assert.That(!File.Exists(tagsPath), "The tags.txt file should have been removed");
            // BL-2163, we are no longer migrating suitableForMakingShells
            Assert.That(storage.MetaData.IsSuitableForMakingShells, Is.False);
            Assert.That(storage.MetaData.IsFolio, Is.True);
            Assert.That(storage.MetaData.IsExperimental, Is.True);
            Assert.That(storage.MetaData.BookletMakingIsAppropriate, Is.True);
            Assert.That(storage.MetaData.AllowUploading, Is.True);
        }
 protected void MakeImageFiles(Bloom.Book.Book book, params string[] images)
 {
     foreach (var image in images)
     {
         MakeSamplePngImageWithMetadata(book.FolderPath.CombineForPath(image + ".png"));
     }
 }
 /// <summary>
 /// The book language data needs to be initialized before handling updatePreview requests, but the
 /// languagesInBook request comes in after the updatePreview request.  So we call this method in
 /// both places with a lock to prevent stepping on each other.  This results in duplicate
 /// calls for AllLanguages, but is safest since the user could leave the publish tab, change the
 /// languages in the book, and then come back to the publish tab with the same book.
 /// </summary>
 private void InitializeLanguagesInBook(ApiRequest request)
 {
     lock (_lockForLanguages)
     {
         _allLanguages = request.CurrentBook.AllPublishableLanguages(countXmatter: true);
         if (_bookForLanguagesToPublish != request.CurrentBook)
         {
             // reinitialize our list of which languages to publish, defaulting to the ones
             // that are complete.
             // Enhance: persist this somehow.
             // Currently the whole Publish screen is regenerated (and languagesInBook retrieved again)
             // whenever a check box is changed, so it's very important not to do this set-to-default
             // code when we haven't changed books.
             _bookForLanguagesToPublish = request.CurrentBook;
             _languagesToPublish.Clear();
             foreach (var kvp in _allLanguages)
             {
                 if (kvp.Value)
                 {
                     _languagesToPublish.Add(kvp.Key);
                 }
             }
         }
     }
 }
        public void BringBookUpToDate_ConvertsTagsToJsonWithExpectedDefaults()
        {
            var storage = GetInitialStorage();
            var locator = (FileLocator) storage.GetFileLocator();
            string root = FileLocator.GetDirectoryDistributedWithApplication(BloomFileLocator.BrowserRoot);
            locator.AddPath(root.CombineForPath("bookLayout"));
            var folder = storage.FolderPath;
            var tagsPath = Path.Combine(folder, "tags.txt");
            File.WriteAllText(tagsPath, "suitableForMakingShells\nexperimental\nfolio\n");
            var collectionSettings =
                new CollectionSettings(new NewCollectionSettings()
                {
                    PathToSettingsFile = CollectionSettings.GetPathForNewSettings(folder, "test"),
                    Language1Iso639Code = "xyz",
                    Language2Iso639Code = "en",
                    Language3Iso639Code = "fr"
                });
            var book = new Bloom.Book.Book(new BookInfo(folder, true), storage, new Mock<ITemplateFinder>().Object,
                collectionSettings,
                new Mock<PageSelection>().Object, new PageListChangedEvent(), new BookRefreshEvent());

            book.BringBookUpToDate(new NullProgress());

            Assert.That(!File.Exists(tagsPath), "The tags.txt file should have been removed");
            // BL-2163, we are no longer migrating suitableForMakingShells
            Assert.That(storage.MetaData.IsSuitableForMakingShells, Is.False);
            Assert.That(storage.MetaData.IsFolio, Is.True);
            Assert.That(storage.MetaData.IsExperimental, Is.True);
            Assert.That(storage.MetaData.BookletMakingIsAppropriate, Is.True);
            Assert.That(storage.MetaData.AllowUploading, Is.True);
        }
        /// <summary>
        /// Make an ePUB out of the specified book. Sets up several instance variables with commonly useful parts of the results.
        /// </summary>
        /// <returns></returns>
        protected virtual ZipFile MakeEpub(string mainFileName, string folderName, Bloom.Book.Book book,
                                           BookInfo.HowToPublishImageDescriptions howToPublishImageDescriptions = BookInfo.HowToPublishImageDescriptions.None,
                                           string branding = "Default", Action <EpubMaker> extraInit = null)
        {
            book.CollectionSettings.BrandingProjectKey = branding;

            // BringBookUpToDate is done on entering the Publish tab, outside the scope of these tests.
            // But note that it must be done AFTER setting the branding (which in Bloom will happen well before
            // entering the Publish tab).
            book.BringBookUpToDate(new NullProgress());
            var epubFolder = new TemporaryFolder(folderName);
            var epubName   = mainFileName + ".epub";
            var epubPath   = Path.Combine(epubFolder.FolderPath, epubName);

            using (var maker = CreateEpubMaker(book))
            {
                maker.Unpaginated = true;                 // Currently we always make unpaginated epubs.
                maker.PublishImageDescriptions = howToPublishImageDescriptions;
                extraInit?.Invoke(maker);
                maker.SaveEpub(epubPath, new NullWebSocketProgress());
            }
            Assert.That(File.Exists(epubPath));
            _epub               = new ZipFile(epubPath);
            _manifestFile       = ExportEpubTestsBaseClass.GetManifestFile(_epub);
            _manifestContent    = StripXmlHeader(GetZipContent(_epub, _manifestFile));
            _manifestDoc        = XDocument.Parse(_manifestContent);
            _defaultSourceValue = $"created from Bloom book on {DateTime.Now:yyyy-MM-dd} with page size A5 Portrait";
            return(_epub);
        }
        public void BringBookUpToDate_MigratesReaderToolsAvailableToToolboxIsOpen()
        {
            var oldMetaData =
                "{\"bookInstanceId\":\"3328aa4a - 2ef3 - 43a8 - a656 - 1d7c6f00444c\",\"folio\":false,\"title\":\"Landscape basic book\",\"baseUrl\":null,\"bookOrder\":null,\"isbn\":\"\",\"bookLineage\":\"056B6F11-4A6C-4942-B2BC-8861E62B03B3\",\"downloadSource\":null,\"license\":\"cc-by\",\"formatVersion\":\"2.0\",\"licenseNotes\":null,\"copyright\":null,\"authors\":null,\"credits\":\"\",\"tags\":[\"<p>\r\n</p>\"],\"pageCount\":0,\"languages\":[],\"langPointers\":null,\"summary\":null,\"allowUploadingToBloomLibrary\":true,\"bookletMakingIsAppropriate\":true,\"uploader\":null,\"tools\":null,\"readerToolsAvailable\":true}";
            var storage = GetInitialStorage();

            // This seems to be needed to let it locate some kind of collection settings.
            var    folder  = storage.FolderPath;
            var    locator = (FileLocator)storage.GetFileLocator();
            string root    = FileLocator.GetDirectoryDistributedWithApplication(BloomFileLocator.BrowserRoot);

            locator.AddPath(root.CombineForPath("bookLayout"));
            var collectionSettings =
                new CollectionSettings(new NewCollectionSettings()
            {
                PathToSettingsFile  = CollectionSettings.GetPathForNewSettings(folder, "test"),
                Language1Iso639Code = "xyz",
                Language2Iso639Code = "en",
                Language3Iso639Code = "fr"
            });
            var book = new Bloom.Book.Book(new BookInfo(folder, true), storage, new Mock <ITemplateFinder>().Object,
                                           collectionSettings,
                                           new Mock <PageSelection>().Object, new PageListChangedEvent(), new BookRefreshEvent());
            var jsonPath = book.BookInfo.MetaDataPath;

            File.WriteAllText(jsonPath, oldMetaData);

            book.BringBookUpToDate(new NullProgress());

            Assert.That(book.BookInfo.ToolboxIsOpen, Is.True);
        }
 ///   <summary>
 ///   Currently used by the image server
 ///   to get thumbnails that are used in the add page dialog. Since this dialog can show
 ///   an enlarged version of the page, we generate these at a higher resolution than usual.
 ///   Also, to make more realistic views of template pages we insert fake text wherever
 ///   there is an empty edit block.
 ///
 ///   The result is cached for possible future use so the caller should not dispose of it.
 ///   </summary>
 /// <param name="book"></param>
 /// <param name="page"></param>
 ///  <param name="isLandscape"></param>
 ///  <returns></returns>
 public Image GetThumbnailForPage(Book.Book book, IPage page, bool isLandscape)
 {
     var pageDom = book.GetThumbnailXmlDocumentForPage(page);
     var thumbnailOptions = new HtmlThumbNailer.ThumbnailOptions()
     {
         BackgroundColor = Color.White,// matches the hand-made previews.
         BorderStyle = HtmlThumbNailer.ThumbnailOptions.BorderStyles.None, // allows the HTML to add its preferred border in the larger preview
         CenterImageUsingTransparentPadding = true
     };
     var pageDiv = pageDom.RawDom.SafeSelectNodes("descendant-or-self::div[contains(@class,'bloom-page')]").Cast<XmlElement>().FirstOrDefault();
     // The actual page size is rather arbitrary, but we want the right ratio for A4.
     // Using the actual A4 sizes in mm makes a big enough image to look good in the larger
     // preview box on the right as well as giving exactly the ratio we want.
     // We need to make the image the right shape to avoid some sort of shadow/box effects
     // that I can't otherwise find a way to get rid of.
     if (isLandscape)
     {
         thumbnailOptions.Width = 297;
         thumbnailOptions.Height = 210;
         pageDiv.SetAttribute("class", pageDiv.Attributes["class"].Value.Replace("Portrait", "Landscape"));
     }
     else
     {
         thumbnailOptions.Width = 210;
         thumbnailOptions.Height = 297;
         // On the offchance someone makes a template with by-default-landscape pages...
         pageDiv.SetAttribute("class", pageDiv.Attributes["class"].Value.Replace("Landscape", "Portrait"));
     }
     // In different books (or even the same one) in the same session we may have portrait and landscape
     // versions of the same template page. So we must use different IDs.
     return _thumbnailProvider.GetThumbnail(page.Id + (isLandscape ? "L" : ""), pageDom, thumbnailOptions);
 }
Example #10
0
        private void TestTemplateInsertion(Bloom.Book.Book book, IPage existingPage, string divContent)
        {
            Mock <IPage> templatePage = CreateTemplatePage(divContent);

            book.InsertPageAfter(existingPage, templatePage.Object);
            AssertPageCount(book, 4);
            Assert.AreEqual("bloom-page somekind A5Portrait", GetPageFromBookDom(book, 1).GetStringAttribute("class"));
        }
Example #11
0
        public BookServer(Book.Factory bookFactory, BookStorage.Factory storageFactory,
						  BookStarter.Factory bookStarterFactory, Configurator.Factory configuratorFactory)
        {
            _bookFactory = bookFactory;
            _storageFactory = storageFactory;
            _bookStarterFactory = bookStarterFactory;
            _configuratorFactory = configuratorFactory;
        }
        public SourceCollectionsList(Book.Book.Factory bookFactory, BookStorage.Factory storageFactory,
			string editableCollectionDirectory,
			IEnumerable<string> sourceRootFolders)
        {
            _bookFactory = bookFactory;
            _storageFactory = storageFactory;
            _editableCollectionDirectory = editableCollectionDirectory;
            _sourceRootFolders = sourceRootFolders;
        }
 protected void MakeVideoFiles(Bloom.Book.Book book, params string[] videos)
 {
     foreach (var video in videos)
     {
         var path = Path.Combine(book.FolderPath, "video", video + ".mp4");
         Directory.CreateDirectory(book.FolderPath.CombineForPath("video"));
         // first 16 bytes from an actual mp4 file.
         File.WriteAllBytes(path, new byte[] { 0x00, 0x00, 0x00, 0x18, 0x66, 0x74, 0x79, 0x70, 0x69, 0x73, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x00 });
     }
 }
Example #14
0
        public void SelectBook(Book book)
        {
            if (_currentSelection == book)
                return;

            //enhance... send out cancellable pre-change event

               _currentSelection = book;

            InvokeSelectionChanged();
        }
Example #15
0
        private void VerifyTranslationGroup(Bloom.Book.Book book, int index, string style, params DivContent[] content)
        {
            var group    = book.RawDom.SelectNodes(".//div[contains(@class, 'bloom-translationGroup')]")[index];
            var editDivs = group.SelectNodes("./div[contains(@class, 'bloom-editable')]");

            Assert.That(editDivs.Count, Is.GreaterThanOrEqualTo(content.Length));             // may keep 'z'?
            foreach (var item in content)
            {
                CheckEditDiv(style, editDivs, item);
            }
        }
        public PageTemplatesApi(SourceCollectionsList  sourceCollectionsList,BookSelection bookSelection,
			PageSelection pageSelection, TemplateInsertionCommand templateInsertionCommand,
			BookThumbNailer thumbNailer, Book.Book.Factory bookFactory, BookStorage.Factory storageFactory)
        {
            _sourceCollectionsList = sourceCollectionsList;
            _bookSelection = bookSelection;
            _pageSelection = pageSelection;
            _templateInsertionCommand = templateInsertionCommand;
            _thumbNailer = thumbNailer;
            _bookFactory = bookFactory;
            _storageFactory = storageFactory;
        }
        // Set up some typical CSS files we DO want to include, even in 'unpaginated' mode
        private static void CreateCommonCssFiles(Bloom.Book.Book book)
        {
            var settingsCollectionPath = Path.Combine(book.FolderPath, "defaultLangStyles.css");

            File.WriteAllText(settingsCollectionPath, "body:{font-family: 'Andika New Basic';}");
            var customCollectionPath = Path.Combine(book.FolderPath, "customCollectionStyles.css");

            File.WriteAllText(customCollectionPath, "body:{font-family: 'Andika New Basic';}");
            var customBookPath = Path.Combine(book.FolderPath, "customBookStyles.css");

            File.WriteAllText(customBookPath, "body:{font-family: 'Andika New Basic';}");
        }
Example #18
0
 public Page(Book book, XmlElement sourcePage,  string caption, /*Func<IPage, Image> getThumbnail,*/ Func<IPage, XmlElement> getDivNodeForThisPageMethod)
 {
     _id = FixPageId(sourcePage.Attributes["id"].Value);
     //_getThumbnail = getThumbnail;
     Guard.AgainstNull(book,"Book");
     Book = book;
     _getDivNodeForThisPageMethod = getDivNodeForThisPageMethod;
     Caption = caption;
     ReadClasses(sourcePage);
     ReadPageTags(sourcePage);
     //ReadPageLabel(sourcePage);
 }
Example #19
0
        public void OneTimeSetup()
        {
            _testFolder = new TemporaryFolder("SpreadsheetImporterWithBookTests");
            // We need 2 layers of temp folder because BringBookUpToDate will change the name of the book
            // folder to match an imported title.
            _bookFolder = new TemporaryFolder(_testFolder, "Book");
            var settings = new NewCollectionSettings();

            settings.Language1.Iso639Code = "en";
            settings.Language1.SetName("English", false);
            settings.SettingsFilePath = Path.Combine(_bookFolder.FolderPath, "dummy");

            var fileLocator = new BloomFileLocator(settings, new XMatterPackFinder(new string[] { }), ProjectContext.GetFactoryFileLocations(),
                                                   ProjectContext.GetFoundFileLocations(), ProjectContext.GetAfterXMatterFileLocations());
            var bookFilePath = Path.Combine(_bookFolder.FolderPath, "testBook.htm");

            if (File.Exists(bookFilePath))             // Shouldn't ever happen, but... just being careful.
            {
                RobustFile.Delete(bookFilePath);
            }
            _dom = SetupTestDom();
            // Write out our test book
            File.WriteAllText(bookFilePath, _dom.RawDom.OuterXml.ToString());
            var storage = new BookStorage(_bookFolder.FolderPath, fileLocator, new BookRenamedEvent(), settings);

            var book = new Bloom.Book.Book(new BookInfo(_bookFolder.FolderPath, true), storage, null,
                                           settings, new Bloom.Edit.PageSelection(),
                                           new PageListChangedEvent(), new BookRefreshEvent());

            // Create the regular production importer
            _importer = new SpreadsheetImporter(null, book, _bookFolder.FolderPath);

            // Set up the internal spreadsheet rows directly.
            var ss             = new InternalSpreadsheet();
            var columnForEn    = ss.AddColumnForLang("en", "English");
            var columnForImage = ss.GetColumnForTag(InternalSpreadsheet.ImageSourceColumnLabel);

            var newTitle = "My new book title";
            var titleRow = new ContentRow(ss);

            titleRow.AddCell(InternalSpreadsheet.BookTitleRowLabel);
            titleRow.SetCell(columnForEn, newTitle);

            var coverImageRow = new ContentRow(ss);

            coverImageRow.AddCell(InternalSpreadsheet.CoverImageRowLabel);
            coverImageRow.SetCell(columnForImage, Path.Combine("images", "Othello 199.jpg"));

            _importer.Import(ss);

            _resultElement = ReadResultingBookToXml(newTitle);
        }
Example #20
0
        /// <summary>
        /// A dumbed down implementation that is able to return a book with the BookInfo and set the book's FolderPath.
        /// </summary>
        /// <returns></returns>
        public override Bloom.Book.Book GetBookFromBookInfo(BookInfo bookInfo, bool forSelectedBook = false)
        {
            var collectionSettings = new Bloom.Collection.CollectionSettings();
            var fileLocator        = new Bloom.BloomFileLocator(collectionSettings, new XMatterPackFinder(Enumerable.Empty <string>()), Enumerable.Empty <string>(), Enumerable.Empty <string>(),
                                                                Enumerable.Empty <string>());

            // Setting storage is neeeded to get it to populate the book's FolderPath.
            var storage = new BookStorage(bookInfo.FolderPath, fileLocator, new Bloom.BookRenamedEvent(), collectionSettings);

            var book = new Bloom.Book.Book(bookInfo, storage);

            return(book);
        }
Example #21
0
        private void VerifyImage(Bloom.Book.Book book, int index, string imageName, int width, int height)
        {
            var div    = book.RawDom.SelectNodes(".//div[contains(@class, 'bloom-imageContainer')]")[index];
            var images = div.SelectNodes("img");

            Assert.That(images, Has.Count.EqualTo(1), "should only be one image in an image container");
            var img = (XmlElement)images[0];

            Assert.That(img.Attributes["src"].Value, Is.EqualTo(imageName));
            Assert.That(img.Attributes["alt"].Value, Does.Contain(imageName));
            Assert.That(img.Attributes["width"].Value, Is.EqualTo(width.ToString()));
            Assert.That(img.Attributes["height"].Value, Is.EqualTo(height.ToString()));
        }
        private static string MakeFakeBloomdFile(Bloom.Book.Book book)
        {
            var srcFile      = Path.Combine(book.FolderPath, "book.htm");
            var filePath     = new TempFileForSafeWriting(Path.Combine(book.FolderPath, "book.bloomd")).TempFilePath;
            var fileContents = File.ReadAllLines(srcFile);

            for (var i = 0; i < 100; i++)
            {
                File.AppendAllLines(filePath, fileContents);
            }

            return(filePath);
        }
 internal string UploadOneBook(BookInstance book, LogBox progressBox, PublishView publishView, bool excludeMusic, out string parseId)
 {
     using (var tempFolder = new TemporaryFolder(Path.Combine("BloomUpload", Path.GetFileName(book.FolderPath))))
     {
         BookUpload.PrepareBookForUpload(ref book, _publishModel.BookServer, tempFolder.FolderPath, progressBox);
         var bookParams = new BookUploadParameters
         {
             ExcludeMusic       = excludeMusic,
             PreserveThumbnails = false,
         };
         return(_uploader.FullUpload(book, progressBox, publishView, bookParams, out parseId));
     }
 }
        public BloomLibraryPublishModel(BookUpload uploader, BookInstance book, PublishModel model)
        {
            Book          = book;
            _uploader     = uploader;
            _publishModel = model;

            _licenseMetadata = Book.GetLicenseMetadata();
            // This is usually redundant, but might not be on old books where the license was set before the new
            // editing code was written.
            Book.SetMetadata(_licenseMetadata);
            _license = _licenseMetadata.License;

            EnsureBookAndUploaderId();
        }
Example #25
0
        protected Bloom.Book.Book CreateBookWithPhysicalFile(string bookHtml, CollectionSettings collectionSettings)
        {
            _collectionSettings = collectionSettings;
            var fileLocator = new BloomFileLocator(new CollectionSettings(), new XMatterPackFinder(new string[] { }), ProjectContext.GetFactoryFileLocations(),
                                                   ProjectContext.GetFoundFileLocations(), ProjectContext.GetAfterXMatterFileLocations());

            File.WriteAllText(Path.Combine(_tempFolder.Path, "book.htm"), bookHtml);

            var storage = new BookStorage(this._tempFolder.Path, fileLocator, new BookRenamedEvent(), _collectionSettings);

            var b = new Bloom.Book.Book(_metadata, storage, _templateFinder.Object,
                                        _collectionSettings,
                                        _pageSelection.Object, _pageListChangedEvent, new BookRefreshEvent());

            return(b);
        }
Example #26
0
        public TestBook(string testName, string content)
        {
            _folder    = new TemporaryFolder(testName);
            BookFolder = _folder.FolderPath;
            BookPath   = Path.Combine(_folder.FolderPath, testName + ".htm");
            File.WriteAllText(BookPath, content);
            var settings    = CreateDefaultCollectionsSettings();
            var codeBaseDir = BloomFileLocator.GetCodeBaseFolder();
            // This is minimal...if the content doesn't specify xmatter Bloom defaults to Traditional
            // and needs the file locator to know this folder so it can find it.
            // May later need to include more folders or allow the individual tests to do so.
            var locator = new FileLocator(new string[] { codeBaseDir + "/../browser/templates/xMatter" });
            var storage = new BookStorage(BookFolder, locator, new BookRenamedEvent(), settings);
            // very minimal...enhance if we need to test something that can really find source collections.
            var templatefinder = new SourceCollectionsList();

            Book = new Bloom.Book.Book(new BookInfo(BookFolder, true), storage, templatefinder, settings, new PageSelection(), new PageListChangedEvent(), new BookRefreshEvent());
        }
        protected Bloom.Book.Book CreateBookWithPhysicalFile(string bookHtml, CollectionSettings collectionSettings)
        {
            _collectionSettings = collectionSettings;
            var fileLocator = new BloomFileLocator(new CollectionSettings(), new XMatterPackFinder(new string[] { }), ProjectContext.GetFactoryFileLocations(),
                                                   ProjectContext.GetFoundFileLocations(), ProjectContext.GetAfterXMatterFileLocations());

            File.WriteAllText(Path.Combine(_tempFolder.Path, "book.htm"), bookHtml);

            var storage = new BookStorage(this._tempFolder.Path, fileLocator, new BookRenamedEvent(), _collectionSettings);

            var b = new Bloom.Book.Book(_metadata, storage, _templateFinder.Object,
                                        _collectionSettings,
                                        _pageSelection.Object, _pageListChangedEvent, new BookRefreshEvent());

            // Some tests need this file early on so it can be copied to the book folder.
            File.WriteAllText(Path.Combine(Path.GetDirectoryName(_tempFolder.Path), "customCollectionStyles.css"), @"/*This is wanted*/");
            return(b);
        }
Example #28
0
        public Book CreateFromSourceBook(Book sourceBook, string containingDestinationFolder)
        {
            string pathToFolderOfNewBook = null;

            Logger.WriteMinorEvent("Starting CreateFromSourceBook({0})", sourceBook.FolderPath);
            try
            {
                var starter = _bookStarterFactory();
                pathToFolderOfNewBook = starter.CreateBookOnDiskFromTemplate(sourceBook.FolderPath, containingDestinationFolder);
                if (Configurator.IsConfigurable(pathToFolderOfNewBook))
                {
                    var c = new Configurator(containingDestinationFolder);
                    if (DialogResult.Cancel == c.ShowConfigurationDialog(pathToFolderOfNewBook))
                    {
                        return null; // the template had a configuration page and they clicked "cancel"
                    }
                    c.ConfigureBook(BookStorage.FindBookHtmlInFolder(pathToFolderOfNewBook));
                }

                var newBookInfo = new BookInfo(pathToFolderOfNewBook,true); // _bookInfos.Find(b => b.FolderPath == pathToFolderOfNewBook);
                if (newBookInfo is ErrorBookInfo)
                {
                    throw ((ErrorBookInfo)newBookInfo).Exception;
                }

                Book newBook = GetBookFromBookInfo(newBookInfo);

                //Hack: this is a bit of a hack, to handle problems where we make the book with the suggested initial name, but the title is still something else
                var name = Path.GetFileName(newBookInfo.FolderPath); // this way, we get "my book 1", "my book 2", etc.
                newBook.SetTitle(name);

                Logger.WriteMinorEvent("Finished CreateFromnewBook({0})", newBook.FolderPath);
                Logger.WriteEvent("CreateFromSourceBook({0})", newBook.FolderPath);
                return newBook;
            }
            catch (Exception)
            {
                Logger.WriteEvent("Cleaning up after error CreateFromSourceBook({0})", pathToFolderOfNewBook);
                //clean up this ill-fated book folder up
                if (!string.IsNullOrEmpty(pathToFolderOfNewBook) && Directory.Exists(pathToFolderOfNewBook))
                    Directory.Delete(pathToFolderOfNewBook, true);
                throw;
            }
        }
        /// <summary>
        /// Check for either "Device16x9Portrait" or "Device16x9Landscape" layout.
        /// Complain to the user if another layout is currently chosen.
        /// </summary>
        /// <remarks>
        /// See https://issues.bloomlibrary.org/youtrack/issue/BL-5274.
        /// </remarks>
        public static void CheckBookLayout(Bloom.Book.Book book, WebSocketProgress progress)
        {
            var layout            = book.GetLayout();
            var desiredLayoutSize = "Device16x9";

            if (layout.SizeAndOrientation.PageSizeName != desiredLayoutSize)
            {
                // The progress object has been initialized to use an id prefix.  So we'll access L10NSharp explicitly here.  We also want to make the string blue,
                // which requires a special argument.
//				var msgFormat = L10NSharp.LocalizationManager.GetString("Common.Note",
//					"Note", "A heading shown above some messages.");
//				progress.MessageWithoutLocalizing(msgFormat, MessageKind.Note);
                var msgFormat = L10NSharp.LocalizationManager.GetString("PublishTab.Android.WrongLayout.Message",
                                                                        "The layout of this book is currently \"{0}\". Bloom Reader will display it using \"{1}\", so text might not fit. To see if anything needs adjusting, go back to the Edit Tab and change the layout to \"{1}\".",
                                                                        "{0} and {1} are book layout tags.");
                var desiredLayout = desiredLayoutSize + layout.SizeAndOrientation.OrientationName;
                var msg           = String.Format(msgFormat, layout.SizeAndOrientation.ToString(), desiredLayout, Environment.NewLine);
                progress.MessageWithoutLocalizing(msg, MessageKind.Note);
            }
        }
Example #30
0
        //review: could do this instead by giving this class the bookselection object
        public void SetBook(Book.Book book)
        {
            //  return;

            if (book == null)
            {
                _thumbNailList.SetItems(new Page[] { });
            }
            else
            {
                _thumbNailList.SetItems(new IPage[] { new PlaceHolderPage() }.Concat(book.GetPages()));
              //  _thumbNailList.SetItems(book.GetPages());

                if(_pageWeThinkShouldBeSelected !=null)
                {
                    //this var will be set previously when someone told us the page we're to select,
                    //but had not yet given us leave to do the time-consuming process of actually
                    //making the thumbnails and showing them.
                    SelectThumbnailWithoutSendingEvent(_pageWeThinkShouldBeSelected);
                }
            }
        }
Example #31
0
        private static Book MakeBook(CollectionSettings collectionSettings, string sourceBookFolderPath)
        {
            var xmatterLocations = new List<string>();
            xmatterLocations.Add(ProjectContext.XMatterAppDataFolder);
            xmatterLocations.Add(FileLocator.GetDirectoryDistributedWithApplication( kpathToSHRPTemplates));
            xmatterLocations.Add(FileLocator.GetDirectoryDistributedWithApplication("xMatter"));
            var locator = new BloomFileLocator(collectionSettings, new XMatterPackFinder(xmatterLocations), new string[] {});

            var starter = new BookStarter(locator,
                                          path =>
                                          new BookStorage(path, locator, new BookRenamedEvent(),
                                                          collectionSettings),
                                          collectionSettings);
            var pathToFolderOfNewBook = starter.CreateBookOnDiskFromTemplate(sourceBookFolderPath, collectionSettings.FolderPath);

            var newBookInfo = new BookInfo(pathToFolderOfNewBook, false /*saying not editable works us around a langdisplay issue*/);

            BookStorage bookStorage = new BookStorage(pathToFolderOfNewBook, locator, new BookRenamedEvent(), collectionSettings);
            var book = new Book(newBookInfo, bookStorage, null,
                            collectionSettings, null, null, null, null);

            return book;
        }
Example #32
0
        /// <summary>
        /// Remove image elements that are invisible due to the book's layout orientation.
        /// </summary>
        /// <remarks>
        /// This code is temporary for Version4.5.  Version4.6 extensively refactors the
        /// electronic publishing code to combine ePUB and BloomReader preparation as much
        /// as possible.
        /// </remarks>
        private static void RemoveInvisibleImageElements(Bloom.Book.Book book)
        {
            var isLandscape = book.GetLayout().SizeAndOrientation.IsLandScape;

            foreach (var img in book.RawDom.SafeSelectNodes("//img").Cast <XmlElement>().ToArray())
            {
                var src = img.Attributes["src"]?.Value;
                if (string.IsNullOrEmpty(src))
                {
                    continue;
                }
                var classes = img.Attributes["class"]?.Value;
                if (string.IsNullOrEmpty(classes))
                {
                    continue;
                }
                if (isLandscape && classes.Contains("portraitOnly") ||
                    !isLandscape && classes.Contains("landscapeOnly"))
                {
                    // Remove this img element since it shouldn't be displayed.
                    img.ParentNode.RemoveChild(img);
                }
            }
        }
 private void HandleThumbnailerErrror(Book.BookInfo bookInfo, Exception error)
 {
     RefreshOneThumbnail(bookInfo, Resources.Error70x70);
 }
 private void ScheduleRefreshOfOneThumbnail(Book.Book book)
 {
     _model.UpdateThumbnailAsync(book, new HtmlThumbNailer.ThumbnailOptions(), RefreshOneThumbnail, HandleThumbnailerErrror);
 }
Example #35
0
        private void CreateFromSourceBook(Book.Book sourceBook)
        {
            var newBook = _bookServer.CreateFromSourceBook(sourceBook, TheOneEditableCollection.PathToDirectory);

            TheOneEditableCollection.AddBookInfo(newBook.BookInfo);

            if (_bookSelection != null)
            {
                _bookSelection.SelectBook(newBook);
            }
            //enhance: would be nice to know if this is a new shell
            if (sourceBook.IsShellOrTemplate)
            {
                Analytics.Track("Create Book", new Dictionary<string, string>() { { "Category", sourceBook.CategoryForUsageReporting } });
            }
            _editBookCommand.Raise(newBook);
        }
        public void MakeThumbnailOfCover(Book.Book book, int height, Control invokeTarget)
        {
            HtmlThumbNailer.ThumbnailOptions options = new HtmlThumbNailer.ThumbnailOptions
            {
                //since this is destined for HTML, it's much easier to handle if there is no pre-padding
                CenterImageUsingTransparentPadding = false
            };

            if (height != -1)
            {
                options.Height = height;
                options.Width = -1;
                options.FileName = "thumbnail-" + height + ".png";
            }
            // else use the defaults

            RebuildThumbNailNow(book, options);
        }
Example #37
0
 protected override void SendBookDoWork(Bloom.Book.Book book, Color backColor)
 {
     throw new COMException("MockUsbPublisher threw a fake COMException in SendBookDoWork.", _exceptionToThrow);
 }
Example #38
0
        private void AddOneBook(Book.BookInfo bookInfo, FlowLayoutPanel flowLayoutPanel)
        {
            var button = new Button(){Size=new Size(90,110)};
            button.Text = ShortenTitleIfNeeded(bookInfo.QuickTitleUserDisplay);
            button.TextImageRelation = TextImageRelation.ImageAboveText;
            button.ImageAlign = ContentAlignment.TopCenter;
            button.TextAlign = ContentAlignment.BottomCenter;
            button.FlatStyle = FlatStyle.Flat;
            button.ForeColor = Palette.TextAgainstDarkBackground ;
            button.FlatAppearance.BorderSize = 0;
            button.ContextMenuStrip = _bookContextMenu;
            button.MouseDown += OnClickBook; //we need this for right-click menu selection, which needs to 1st select the book
            //doesn't work: item.DoubleClick += (sender,arg)=>_model.DoubleClickedBook();

            button.Font = bookInfo.IsEditable ? _editableBookFont : _collectionBookFont;

            button.Tag=bookInfo;

            Image thumbnail = Resources.PagePlaceHolder;;
            _bookThumbnails.Images.Add(bookInfo.Id, thumbnail);
            button.ImageIndex = _bookThumbnails.Images.Count - 1;
            flowLayoutPanel.Controls.Add(button);

            Image img;

            //review: we could do this at idle time, too:
            if (bookInfo.TryGetPremadeThumbnail(out img))
            {
                RefreshOneThumbnail(bookInfo, img);
            }
            else
            {
                //show this one for now, in the background someone will do the slow work of getting us a better one
                RefreshOneThumbnail(bookInfo,Resources.placeHolderBookThumbnail);
                //hack to signal that we need to make a real one when get a chance
                button.ImageIndex = 999;
            }
            _buttonsNeedingSlowUpdate.Enqueue(button);

            //			bookInfo.GetThumbNailOfBookCoverAsync(bookInfo.Type != Book.Book.BookType.Publication,
            //				                                  image => RefreshOneThumbnail(bookInfo, image),
            //												  error=> RefreshOneThumbnail(bookInfo, Resources.Error70x70));
        }
 /// <summary>
 /// Will make a new thumbnail (or throw) UNLESS the thumbnail is readonly, in which case it will do nothing.
 /// </summary>
 /// <param name="book"></param>
 /// <param name="thumbnailOptions"></param>
 public void RebuildThumbNailNow(Book.Book book, HtmlThumbNailer.ThumbnailOptions thumbnailOptions)
 {
     RebuildThumbNail(book, thumbnailOptions, (info, image) => { },
         (info, ex) =>
         {
             throw ex;
         }, false);
 }
        public void BringBookUpToDate_MigratesReaderToolsAvailableToToolboxIsOpen()
        {
            var oldMetaData =
                "{\"bookInstanceId\":\"3328aa4a - 2ef3 - 43a8 - a656 - 1d7c6f00444c\",\"folio\":false,\"title\":\"Landscape basic book\",\"baseUrl\":null,\"bookOrder\":null,\"isbn\":\"\",\"bookLineage\":\"056B6F11-4A6C-4942-B2BC-8861E62B03B3\",\"downloadSource\":null,\"license\":\"cc-by\",\"formatVersion\":\"2.0\",\"licenseNotes\":null,\"copyright\":null,\"authors\":null,\"credits\":\"\",\"tags\":[\"<p>\r\n</p>\"],\"pageCount\":0,\"languages\":[],\"langPointers\":null,\"summary\":null,\"allowUploadingToBloomLibrary\":true,\"bookletMakingIsAppropriate\":true,\"uploader\":null,\"tools\":null,\"readerToolsAvailable\":true}";
            var storage = GetInitialStorage();

            // This seems to be needed to let it locate some kind of collection settings.
            var folder = storage.FolderPath;
            var locator = (FileLocator)storage.GetFileLocator();
            string root = FileLocator.GetDirectoryDistributedWithApplication(BloomFileLocator.BrowserRoot);

            locator.AddPath(root.CombineForPath("bookLayout"));
            var collectionSettings =
                new CollectionSettings(new NewCollectionSettings()
                {
                    PathToSettingsFile = CollectionSettings.GetPathForNewSettings(folder, "test"),
                    Language1Iso639Code = "xyz",
                    Language2Iso639Code = "en",
                    Language3Iso639Code = "fr"
                });
            var book = new Bloom.Book.Book(new BookInfo(folder, true), storage, new Mock<ITemplateFinder>().Object,
                collectionSettings,
                new Mock<PageSelection>().Object, new PageListChangedEvent(), new BookRefreshEvent());
            var jsonPath = book.BookInfo.MetaDataPath;
            File.WriteAllText(jsonPath, oldMetaData);

            book.BringBookUpToDate(new NullProgress());

            Assert.That(book.BookInfo.ToolboxIsOpen, Is.True);
        }
Example #41
0
            public ReportInfo(string heading, string detailMessage, Exception exception, Bloom.Book.Book book,
                              string bookName, string email, string firstName, string surname, bool isHeadingPreEncoded = false)
            {
                if (isHeadingPreEncoded)
                {
                    HeadingHtml = heading;
                }
                else
                {
                    HeadingHtml = UrlPathString.CreateFromUnencodedString(heading).HtmlXmlEncoded;
                }

                this.DetailedMessage = detailMessage;
                this.Exception       = exception;
                this.Book            = book;
                this.BookName        = bookName;
                this.UserEmail       = email;
                this.UserFirstName   = firstName;
                this.UserSurname     = surname;
            }
Example #42
0
        public void GetTextOfContentPagesAsJson_OmitsUnwantedPages()
        {
            var htmlLeveledReader = $@"<html><head><meta charset='UTF-8'></meta></head>
<body class='leveled-reader' data-l1='en' data-l2='fr' data-l3='es'>
    <!-- ignore page with bloom-frontMatter class -->
    <div class='bloom-page bloom-frontMatter' id='b8408838-e9ed-4d76-bb8a-24ad0708b329' lang='fr'>
        <div class='marginBox'>
            <div class='bloom-translationGroup bookTitle' data-default-languages='V,N1'>
                <div class='bloom-editable bloom-content1 bloom-visibility-code-on' lang='en'>
                    <p>Level Two</p>
                </div>
            </div>
            <div class='bloom-imageContainer' title='Name: aor_IN16.png'>
                <img src='aor_IN16.png'></img>
                <div class='bloom-translationGroup bloom-imageDescription'>
                    <div class='bloom-editable bloom-content1 bloom-visibility-code-on' lang='en'>cat</div>
                </div>
            </div>
        </div>
    </div>
    <!-- ignore page with bloom-nonprinting class -->
    <div class='bloom-page bloom-noreader bloom-nonprinting screen-only' id='33b7e4c5-6cd1-4611-a50f-85837143cbf6' lang=''>
        <div class='pageLabel' data-i18n='TemplateBooks.PageLabel.Translation Instructions' lang='en'>Translation Instructions</div>
        <div class='marginBox'>
            <div class='split-pane-component-inner'>
                <div class='bloom-translationGroup' data-default-languages='*'>
                    <div class='bloom-editable bloom-content1 bloom-visibility-code-on' data-book='' lang='en' contenteditable='true'>
                        <p>Instructions in vernacular language ...</p>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <!-- skip over page with no bloom-content1 content apart from image descriptions -->
	<div class='bloom-page numberedPage' id='a2ecb8be-5c7f-440d-9ef5-d503476211cd' data-page-number='1' lang=''>
        <div class='pageLabel' data-i18n='TemplateBooks.PageLabel.Just a Picture' lang='en'>Just a Picture</div>
        <div class='marginBox'>
            <div class='split-pane-component-inner'>
                <div class='bloom-imageContainer' title='Name: aor_acc034m.png'>
                    <img src='aor_acc034m.png' alt='cat staring at something outside the picture'></img>
                    <div class='bloom-translationGroup bloom-imageDescription bloom-trailingElement'>
                        <div class='bloom-editable bloom-content1 bloom-visibility-code-on' lang='en'>
                            <p>cat staring at something outside the picture</p>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <!-- include content page with bloom-content1 content, ignoring image description -->
    <div class='bloom-page numberedPage' id='85a320a4-b73f-4149-87a1-9a1297ef04b0' data-page-number='2' lang=''>
        <div class='pageLabel' data-i18n='TemplateBooks.PageLabel.Basic Text &amp; Picture' lang='en'>Basic Text &amp; Picture</div>
        <div class='marginBox'>
            <div class='split-pane horizontal-percent'>
                <div class='split-pane-component position-top'>
                    <div class='split-pane-component-inner'>
                        <div class='bloom-imageContainer bloom-leadingElement' title='Name: aor_Cat3.png'>
                            <img src='aor_Cat3.png' alt='cat lying down and staring at you through slitted eyes'></img>
                            <div class='bloom-translationGroup bloom-imageDescription'>
                                <div class='bloom-editable bloom-content1 bloom-visibility-code-on' lang='en'>
                                    <p>cat lying down and staring at you through slitted eyes</p>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                <div class='split-pane-divider horizontal-divider'></div>
                <div class='split-pane-component position-bottom'>
                    <div class='split-pane-component-inner'>
                        <div class='bloom-translationGroup' data-default-languages='auto'>
                            <div class='bloom-editable bloom-content1 bloom-visibility-code-on' id='i57437cd1-c55c-499e-b0c3-d7195fba5f11' lang='en'>
                                <p>A cat stares at you.</p>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <!-- include content page with empty bloom-content1 content, ignoring image description -->
    <div class='bloom-page numberedPage' id='d46e4259-2a99-4197-b21d-bf97a992b7d0' data-page-number='3' lang=''>
        <div class='pageLabel' data-i18n='TemplateBooks.PageLabel.Basic Text &amp; Picture' lang='en'>Basic Text &amp; Picture</div>
        <div class='marginBox'>
            <div class='split-pane horizontal-percent'>
                <div class='split-pane-component position-top'>
                    <div class='split-pane-component-inner'>
                        <div class='bloom-imageContainer' title='Name: aor_ACC029M.png'>
                            <img src='aor_ACC029M.png' alt='cat sleeping in a box that is just large enough'></img>
                            <div class='bloom-translationGroup bloom-imageDescription'>
                                <div class='bloom-editable bloom-content1 bloom-visibility-code-on' lang='en'>
                                    <p>cat sleeping in a box that is just large enough</p>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                <div class='split-pane-divider horizontal-divider'></div>
                <div class='split-pane-component position-bottom'>
                    <div class='split-pane-component-inner'>
                        <div class='bloom-translationGroup' data-default-languages='auto'>
                            <div class='bloom-editable bloom-content1 bloom-visibility-code-on' lang='en'>
                                <p></p>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <!-- include content page with bloom-content1 content and no image -->
    <div class='bloom-page numberedPage' id='5a424678-ec70-4c97-a547-015ff38dfd11' data-page-number='4' lang=''>
        <div class='marginBox'>
            <div class='bloom-translationGroup bloom-trailingElement' data-default-languages='auto'>
                <div class='bloom-editable normal-style bloom-content1 bloom-visibility-code-on' lang='en'>
                    <p>See the two kittens.</p>
                </div>
            </div>
        </div>
    </div>
	<!-- include page with non-vernacular text if it also has vernacular text -->
    <div class='bloom-page numberedPage' id='ebbd7f47-05fa-4e6d-a7a1-cb526bb5efb8' data-page-number='5' lang=''>
        <div class='pageLabel' data-i18n='TemplateBooks.PageLabel.Custom' lang='en'>Custom</div>
        <div class='marginBox'>
            <div class='split-pane horizontal-percent'>
                <div class='split-pane-component position-top'>
                    <div class='split-pane-component-inner' min-width='60px 150px 250px' min-height='60px 150px'>
                        <div class='bloom-translationGroup bloom-trailingElement' data-default-languages='N1'>
                            <div class='bloom-editable bloom-contentNational1 bloom-visibility-code-on' lang='fr'>
                                <p>national language text</p>
                            </div>
                        </div>
                    </div>
                </div>
                <div class='split-pane-divider horizontal-divider' title='33.2%'></div>
                <div class='split-pane-component position-bottom'>
                    <div class='split-pane-component position-top'>
                        <div class='split-pane-component-inner' min-width='60px 150px 250px' min-height='60px 150px'>
                            <div class='bloom-translationGroup bloom-trailingElement' data-default-languages='V'>
                                <div class='bloom-editable bloom-content1 bloom-visibility-code-on' lang='en'>
                                    <p>local language text</p>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
	<!-- ignore page with bloom-ignoreForReaderStats class -->
    <div class='bloom-page numberedPage bloom-ignoreForReaderStats' id='ebad7a47-05fa-4e6d-a7a1-cb526bb5efb8' data-page-number='6' lang=''>
        <div class='pageLabel' data-i18n='TemplateBooks.PageLabel.Custom' lang='en'>Custom</div>
        <div class='marginBox'>
            <div class='split-pane horizontal-percent'>
                <div class='split-pane-component position-top'>
                    <div class='split-pane-component-inner' min-width='60px 150px 250px' min-height='60px 150px'>
                        <div class='bloom-translationGroup bloom-trailingElement' data-default-languages='N1'>
                            <div class='bloom-editable normal-style bloom-contentNational1 bloom-visibility-code-on' lang='fr'>
                                <p>This is in the national language.</p>
                            </div>
                        </div>
                    </div>
                </div>
                <div class='split-pane-divider horizontal-divider' title='33.2%'></div>
                <div class='split-pane-component position-bottom'>
                    <div class='split-pane-component position-top'>
                        <div class='split-pane-component-inner' min-width='60px 150px 250px' min-height='60px 150px'>
                            <div class='bloom-translationGroup bloom-trailingElement' data-default-languages='V'>
                                <div class='bloom-editable normal-style bloom-content1 bloom-visibility-code-on' lang='en'>
                                    <p>This is in the local language.</p>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <!-- ignore page with bloom-backMatter class -->
    <div class='bloom-page titlePage bloom-backMatter' id='0f8d4d80-0519-42b6-bcde-6362b99ed1ff' lang='fr'>
        <div class='pageLabel' lang='en' data-i18n='TemplateBooks.PageLabel.Title Page'>Title Page</div>
        <div class='marginBox'>
            <div class='bloom-translationGroup' data-default-languages='V,N1' id='titlePageTitleBlock'>
                <div class='bloom-editable bloom-content1 bloom-visibility-code-on' lang='en'>
                    <p>Level Two</p>
                </div>
            </div>
        </div>
    </div>
</body></html>
";
            var doc = new XmlDocument();

            doc.LoadXml(htmlLeveledReader);
            var dom     = new HtmlDom(doc);
            var storage = CreateMockStorage(dom, "GetPagesForReader");
            var book    = new Bloom.Book.Book(storage.Object.BookInfo, storage.Object);

            _bookSelection.SelectBook(book);

            var result = ApiTest.GetString(_server, "readers/io/textOfContentPages");

            Assert.That(result, Is.EqualTo("{\"85a320a4-b73f-4149-87a1-9a1297ef04b0\":\"<p>A cat stares at you.</p>\",\"d46e4259-2a99-4197-b21d-bf97a992b7d0\":\"<p />\",\"5a424678-ec70-4c97-a547-015ff38dfd11\":\"<p>See the two kittens.</p>\",\"ebbd7f47-05fa-4e6d-a7a1-cb526bb5efb8\":\"<p>local language text</p>\"}"));
        }
        public void GetThumbNailOfBookCover(Book.Book book, HtmlThumbNailer.ThumbnailOptions thumbnailOptions, Action<Image> callback, Action<Exception> errorCallback, bool async)
        {
            if (book is ErrorBook)
            {
                callback(Resources.Error70x70);
                return;
            }
            try
            {
                if (book.HasFatalError) //NB: we might not know yet... we don't fully load every book just to show its thumbnail
                {
                    callback(Resources.Error70x70);
                    return;
                }
                Image thumb;
                if (book.Storage.TryGetPremadeThumbnail(thumbnailOptions.FileName, out thumb))
                {
                    callback(thumb);
                    return;
                }

                var dom = book.GetPreviewXmlDocumentForFirstPage();
                if (dom == null)
                {
                    callback(Resources.Error70x70);
                    return;
                }
                string folderForCachingThumbnail;

                folderForCachingThumbnail = book.Storage.FolderPath;
                _thumbnailProvider.GetThumbnail(folderForCachingThumbnail, book.Storage.Key, dom, thumbnailOptions, callback, errorCallback, async);
            }
            catch (Exception err)
            {
                callback(Resources.Error70x70);
                Debug.Fail(err.Message);
            }
        }
        /// <summary>
        /// Will call either 'callback' or 'errorCallback' UNLESS the thumbnail is readonly, in which case it will do neither.
        /// </summary>
        /// <param name="book"></param>
        /// <param name="thumbnailOptions"></param>
        /// <param name="callback"></param>
        /// <param name="errorCallback"></param>
        private void RebuildThumbNail(Book.Book book, HtmlThumbNailer.ThumbnailOptions thumbnailOptions,
			Action<BookInfo, Image> callback, Action<BookInfo, Exception> errorCallback, bool async)
        {
            try
            {
                if(!book.Storage.RemoveBookThumbnail(thumbnailOptions.FileName))
                {
                    // thumbnail is marked readonly, so just use it
                    Image thumb;
                    book.Storage.TryGetPremadeThumbnail(thumbnailOptions.FileName, out thumb);
                    callback(book.BookInfo, thumb);
                    return;
                }

                _thumbnailProvider.RemoveFromCache(book.Storage.Key);

                thumbnailOptions.BorderStyle = (book.Type == Book.Book.BookType.Publication)
                    ? HtmlThumbNailer.ThumbnailOptions.BorderStyles.Solid
                    : HtmlThumbNailer.ThumbnailOptions.BorderStyles.Dashed;
                GetThumbNailOfBookCover(book, thumbnailOptions, image => callback(book.BookInfo, image),
                    error =>
                    {
                        //Enhance; this isn't a very satisfying time to find out, because it's only going to happen if we happen to be rebuilding the thumbnail.
                        //It does help in the case where things are bad, so no thumbnail was created, but by then probably the user has already had some big error.
                        //On the other hand, given that they have this bad book in their collection now, it's good to just remind them that it's broken and not
                        //keep showing green error boxes.
                        book.CheckForErrors();
                        errorCallback(book.BookInfo, error);
                    }, async);
            }
            catch(Exception error)
            {
                NonFatalProblem.Report(ModalIf.Alpha, PassiveIf.All, "Problem creating book thumbnail ", exception: error);
            }
        }
        private void RefreshOneThumbnail(Book.BookInfo bookInfo, Image image)
        {
            if (IsDisposed)
                return;
            try
            {
                var imageIndex = _bookThumbnails.Images.IndexOfKey(bookInfo.Id);
                if (imageIndex > -1)
                {
                    _bookThumbnails.Images[imageIndex] = image;
                    var button = FindBookButton(bookInfo);
                    button.Image = IsUsableBook(button) ? image : MakeDim(image);
                }
            }

            catch (Exception e)
            {
                Logger.WriteEvent("Error refreshing thumbnail. "+e.Message);
            #if DEBUG
                throw;
            #endif
            }
        }
Example #46
0
 private Button FindBookButton(Book.BookInfo bookInfo)
 {
     return AllBookButtons().FirstOrDefault(b => b.Tag == bookInfo);
 }
        /// <summary>
        /// Try the number of times given to make the ePUB before letting an ApplicationException be thrown.
        /// </summary>
        /// <remarks>
        /// The ExportEpubTests (including ExportEpubWithVideoTests and EpubValidAndAccessible) fail rather
        /// consistently (but not always) on Linux even though they always succeed on Windows.  The failure
        /// mode is always having an ApplicationException thrown from inside PublishHelper.IsDisplayed
        /// while making the ePUB with the message "Failure to completely load visibility document in
        /// RemoveUnwantedContent".  Converting all three subclasses to single class removed this failure
        /// mode on Linux, but introduced a failure mode on Windows where every test run reported two
        /// failures in this set of tests.  Various attempts with lock on Mutex on the MakeEpub method
        /// had little to no effect.  Implementing this retry method is the only solution that I've come
        /// up with that appears to work on both platforms.  A test run of 20 times through all the export
        /// ePUB tests showed that no more than two tries were ever needed to succeed, but two tries were
        /// needed at least once per run on average.
        /// </remarks>
        protected ZipFile MakeEpubWithRetries(int maxRetry, string mainFileName, string folderName, Bloom.Book.Book book,
                                              BookInfo.HowToPublishImageDescriptions howToPublishImageDescriptions = BookInfo.HowToPublishImageDescriptions.None,
                                              string branding = "Default", Action <EpubMaker> extraInit = null)
        {
            ZipFile zipFile = null;

            for (int i = 1; i <= maxRetry; ++i)
            {
                try
                {
                    zipFile = MakeEpub(mainFileName, folderName, book, howToPublishImageDescriptions, branding, extraInit);
                    if (i > 1)
                    {
                        Console.WriteLine($"MakeEpub(\"{mainFileName}\",\"{folderName}\",...) succeeded on try number {i} to load the visibility document.");
                    }
                    break;
                }
                catch (ApplicationException e)
                {
                    if (e.Message == "Failure to completely load visibility document in RemoveUnwantedContent")
                    {
                        if (i < maxRetry)
                        {
                            continue;
                        }
                        Console.WriteLine($"MakeEpub(\"{mainFileName}\",\"{folderName}\",...) failed {maxRetry} times to complete loading the visibility document.");
                    }
                    throw;
                }
            }
            return(zipFile);
        }
        /// <summary>
        /// Will call either 'callback' or 'errorCallback' UNLESS the thumbnail is readonly, in which case it will do neither.
        /// </summary>
        /// <param name="book"></param>
        /// <param name="thumbnailOptions"></param>
        /// <param name="callback"></param>
        /// <param name="errorCallback"></param>
        public void RebuildThumbNailAsync(Book.Book book, HtmlThumbNailer.ThumbnailOptions thumbnailOptions,
			Action<BookInfo, Image> callback, Action<BookInfo, Exception> errorCallback)
        {
            RebuildThumbNail(book, thumbnailOptions, callback, errorCallback, true);
        }
Example #49
0
 private void ScheduleRefreshOfOneThumbnail(Book.Book book)
 {
     _model.UpdateThumbnailAsync(book, RefreshOneThumbnail, HandleThumbnailerErrror);
 }
Example #50
0
        //, BookCollection collection)
        public bool DeleteBook(Book.Book book)
        {
            Debug.Assert(book == _bookSelection.CurrentSelection);

            if (_bookSelection.CurrentSelection != null && _bookSelection.CurrentSelection.CanDelete)
            {
                var title = _bookSelection.CurrentSelection.TitleBestForUserDisplay;
                var confirmRecycleDescription = L10NSharp.LocalizationManager.GetString("CollectionTab.ConfirmRecycleDescription", "The book '{0}'");
                if (Bloom.ConfirmRecycleDialog.JustConfirm(string.Format(confirmRecycleDescription, title)))
                {
                    TheOneEditableCollection.DeleteBook(book.BookInfo);
                    _bookSelection.SelectBook(null);
                    _sendReceiver.CheckInNow(string.Format("Deleted '{0}'", title));
                    return true;
                }
            }
            return false;
        }
Example #51
0
        private void AssertPageCount(Bloom.Book.Book book, int expectedCount)
        {
            var result = book.RawDom.StripXHtmlNameSpace();

            AssertThatXmlIn.Dom(result).HasSpecifiedNumberOfMatchesForXpath("//div[contains(@class, 'bloom-page')]", expectedCount);
        }
Example #52
0
 public void SelectBook(Book.Book book)
 {
     _bookSelection.SelectBook(book);
 }
Example #53
0
        private XmlNode GetPageFromBookDom(Bloom.Book.Book book, int pageNumber0Based)
        {
            var result = book.RawDom.StripXHtmlNameSpace();

            return(result.SafeSelectNodes("//div[contains(@class, 'bloom-page')]", null)[pageNumber0Based]);
        }
Example #54
0
 public void UpdateThumbnailAsync(Book.Book book, Action<Book.BookInfo, Image> callback, Action<Book.BookInfo, Exception> errorCallback)
 {
     book.RebuildThumbNailAsync(callback,errorCallback);
 }
 private EpubMakerAdjusted CreateEpubMaker(Bloom.Book.Book book)
 {
     return(new EpubMakerAdjusted(book, new BookThumbNailer(_thumbnailer.Object), _bookServer));
 }
        public static void InitializeLanguages(BookInstance book)
        {
            var allLanguages = book.AllPublishableLanguages();

            var bookInfo = book.BookInfo;

            Debug.Assert(bookInfo?.MetaData != null, "Precondition: MetaData must not be null");

            if (bookInfo.PublishSettings.BloomLibrary.TextLangs == null)
            {
                bookInfo.PublishSettings.BloomLibrary.TextLangs = new Dictionary <string, InclusionSetting>();
            }

            // reinitialize our list of which languages to publish, defaulting to the ones that are complete.
            foreach (var kvp in allLanguages)
            {
                var langCode = kvp.Key;

                // First, check if the user has already explicitly set the value. If so, we'll just use that value and be done.
                if (bookInfo.PublishSettings.BloomLibrary.TextLangs.TryGetValue(langCode, out InclusionSetting checkboxValFromSettings))
                {
                    if (checkboxValFromSettings.IsSpecified())
                    {
                        continue;
                    }
                }

                // Nope, either no value exists or the value was some kind of default value.
                // Compute (or recompute) what the value should default to.
                bool isChecked = kvp.Value || IsRequiredLanguageForBook(langCode, book);

                var newInitialValue = isChecked ? InclusionSetting.IncludeByDefault : InclusionSetting.ExcludeByDefault;
                bookInfo.PublishSettings.BloomLibrary.TextLangs[langCode] = newInitialValue;
            }

            // Initialize the Talking Book Languages settings
            if (bookInfo.PublishSettings.BloomLibrary.AudioLangs == null)
            {
                bookInfo.PublishSettings.BloomLibrary.AudioLangs = new Dictionary <string, InclusionSetting>();
                var allLangCodes = allLanguages.Select(x => x.Key);
                foreach (var langCode in allLangCodes)
                {
                    bookInfo.PublishSettings.BloomLibrary.AudioLangs[langCode] = InclusionSetting.IncludeByDefault;
                }
            }

            if (bookInfo.PublishSettings.BloomLibrary.SignLangs == null)
            {
                bookInfo.PublishSettings.BloomLibrary.SignLangs = new Dictionary <string, InclusionSetting>();
            }
            var collectionSignLangCode = book.CollectionSettings.SignLanguageIso639Code;

            // User may have unset or modified the sign language for the collection in which case we need to exclude the old one it if it was previously included.
            foreach (var includedSignLangCode in bookInfo.PublishSettings.BloomLibrary.SignLangs.IncludedLanguages().ToList())
            {
                if (includedSignLangCode != collectionSignLangCode)
                {
                    bookInfo.PublishSettings.BloomLibrary.SignLangs[includedSignLangCode] = InclusionSetting.ExcludeByDefault;
                }
            }
            // Include the collection sign language by default unless the user excluded it.
            if (!string.IsNullOrEmpty(collectionSignLangCode))
            {
                if (!bookInfo.PublishSettings.BloomLibrary.SignLangs.ContainsKey(collectionSignLangCode) ||
                    bookInfo.PublishSettings.BloomLibrary.SignLangs[collectionSignLangCode] != InclusionSetting.Exclude)
                {
                    bookInfo.PublishSettings.BloomLibrary.SignLangs[collectionSignLangCode] = InclusionSetting.IncludeByDefault;
                }
            }

            // The metadata may have been changed, so save it.
            bookInfo.Save();
        }
Example #57
0
        /// <summary>
        /// Common routine used in normal upload and bulk upload.
        /// </summary>
        /// <param name="book"></param>
        /// <param name="progressBox"></param>
        /// <param name="publishView"></param>
        /// <param name="parseId"></param>
        /// <param name="languages"></param>
        /// <param name="invokeTarget"></param>
        /// <returns></returns>
        internal string FullUpload(Book.Book book, LogBox progressBox, PublishView publishView, string[] languages, out string parseId, Form invokeTarget = null)
        {
            var bookFolder = book.FolderPath;
            parseId = ""; // in case of early return
            // Set this in the metadata so it gets uploaded. Do this in the background task as it can take some time.
            // These bits of data can't easily be set while saving the book because we save one page at a time
            // and they apply to the book as a whole.
            book.BookInfo.LanguageTableReferences = _parseClient.GetLanguagePointers(book.CollectionSettings.MakeLanguageUploadData(languages));
            book.BookInfo.PageCount = book.GetPages().Count();
            book.BookInfo.Save();
            progressBox.WriteStatus(LocalizationManager.GetString("PublishTab.Upload.MakingThumbnail", "Making thumbnail image..."));
            //the largest thumbnail I found on Amazon was 300px high. Prathambooks.org about the same.
            _thumbnailer.MakeThumbnailOfCover(book, 70, invokeTarget); // this is a sacrificial one to prime the pump, to fix BL-2673
            _thumbnailer.MakeThumbnailOfCover(book, 70, invokeTarget);
            if (progressBox.CancelRequested)
                return "";
            _thumbnailer.MakeThumbnailOfCover(book, 256, invokeTarget);
            if (progressBox.CancelRequested)
                return "";

            // It is possible the user never went back to the Collection tab after creating/updating the book, in which case
            // the 'normal' thumbnail never got created/updating. See http://issues.bloomlibrary.org/youtrack/issue/BL-3469.
            _thumbnailer.MakeThumbnailOfCover(book, invokeTarget);
            if (progressBox.CancelRequested)
                return "";

            var uploadPdfPath = UploadPdfPath(bookFolder);
            // If there is not already a locked preview in the book folder
            // (which we take to mean the user has created a customized one that he prefers),
            // make sure we have a current correct preview and then copy it to the book folder so it gets uploaded.
            if (!FileUtils.IsFileLocked(uploadPdfPath))
            {
                progressBox.WriteStatus(LocalizationManager.GetString("PublishTab.Upload.MakingPdf", "Making PDF Preview..."));
                publishView.MakePublishPreview();
                if (RobustFile.Exists(publishView.PdfPreviewPath))
                {
                    RobustFile.Copy(publishView.PdfPreviewPath, uploadPdfPath, true);
                }
            }
            if (progressBox.CancelRequested)
                return "";
            return UploadBook(bookFolder, progressBox, out parseId, Path.GetFileName(uploadPdfPath));
        }
 public void MakeThumbnailOfCover(Book.Book book, Control invokeTarget)
 {
     MakeThumbnailOfCover(book, -1, invokeTarget);
 }