private void RefreshPreview(EpubPublishUiSettings newSettings) { // We have seen some exceptions thrown during refresh that cause a pretty yellow // dialog box pop up informing the user, e.g., that the program couldn't find // "api/publish/epub/updatePreview". Rather than confuse the user, we catch such // exceptions here and retry a limited number of times. // See https://issues.bloomlibrary.org/youtrack/issue/BL-6763. Exception exception = null; for (int i = 0; i < 3; ++i) { try { if (UpdatePreview(newSettings, true)) { _webSocketServer.SendString(kWebsocketContext, kWebsocketEventId_epubReady, _previewSrc); } return; } catch (Exception e) { exception = e; // the original stack trace is rather important for post mortem debugging! } } // Notify the user gently that updating the ePUB preview failed. NonFatalProblem.Report(ModalIf.None, PassiveIf.All, "Something went wrong while making the ePUB preview.", "Updating the ePUB preview failed: " + exception.Message, exception); }
public void GetEpubSettingsForCurrentBook(EpubPublishUiSettings epubPublishUiSettings) { var info = _bookSelection.CurrentSelection.BookInfo; epubPublishUiSettings.howToPublishImageDescriptions = info.MetaData.Epub_HowToPublishImageDescriptions; epubPublishUiSettings.removeFontSizes = info.MetaData.Epub_RemoveFontSizes; }
public void UpdateAndSave(EpubPublishUiSettings newSettings, string path, bool force, WebSocketProgress progress = null) { bool succeeded; do { lock (this) { succeeded = UpdatePreview(newSettings, force, progress); if (succeeded) { EpubMaker.SaveEpub(path, _progress); _webSocketServer.SendString(kWebsocketContext, kWebsocketEventId_epubReady, _previewSrc); } } } while (!succeeded && !EpubMaker.AbortRequested); // try until we get a complete epub, not interrupted by user changing something. }
public bool UpdatePreview(EpubPublishUiSettings newSettings, bool force, WebSocketProgress progress = null) { _progress = progress ?? _standardProgress.WithL10NPrefix("PublishTab.Epub."); if (Program.RunningOnUiThread) { // There's some stuff inside this lock that has to run on the UI thread. // If we lock the UI thread here, we can deadlock the whole program. throw new ApplicationException(@"Must not attempt to make epubs on UI thread...will produce deadlocks"); } lock (_epubMakerLock) { if (EpubMaker != null) { EpubMaker.AbortRequested = false; } _stagingEpub = true; } // For some unknown reason, if the accessibility window is showing, some of the browser navigation // that is needed to accurately determine which content is visible simply doesn't happen. // It would be disconcerting if it popped to the top after we close it and reopen it. // So, we just close the window if it is showing when we do this. See BL-7807. // Except that opening the Ace Checker tab invokes this code path in a way that works without the // deadlock (or whatever causes the failure). This call can be detected by the progress argument not // being null. The Refresh button on the AccessibilityCheckWindow also uses this code path in the // same way, so the next two lines also allow that Refresh button to work. See BL-9341 for why // the original fix is inadequate. if (progress == null) { AccessibilityChecker.AccessibilityCheckWindow.StaticClose(); } try { _webSocketServer.SendString(kWebsocketContext, "startingEbookCreation", _previewSrc); var htmlPath = _bookSelection.CurrentSelection.GetPathHtmlFile(); var newVersion = Book.Book.ComputeHashForAllBookRelatedFiles(htmlPath); bool previewIsAlreadyCurrent; lock (_epubMakerLock) { previewIsAlreadyCurrent = _desiredEpubSettings == newSettings && EpubMaker != null && newVersion == _bookVersion && !EpubMaker.AbortRequested && !force; } if (previewIsAlreadyCurrent) { SaveAsEpub(); // just in case there's a race condition where we haven't already saved it. return(true); // preview is already up to date. } _desiredEpubSettings = newSettings; // clear the obsolete preview, if any; this also ensures that when the new one gets done, // we will really be changing the src attr in the preview iframe so the display will update. _webSocketServer.SendEvent(kWebsocketContext, kWebsocketEventId_epubReady); _bookVersion = newVersion; ReportProgress(LocalizationManager.GetString("PublishTab.Epub.PreparingPreview", "Preparing Preview")); // This three-tries loop is an attempt to recover from a weird state the system sometimes gets into // where a browser won't navigate to a temporary page that the EpubMaker uses. I'm not sure it actually // helps, once the system gets into this state even a brand new browser seems to have the same problem. // Usually there will be no exception, and the loop breaks at the end of the first iteration. for (int i = 0; i < 3; i++) { try { if (!PublishHelper.InPublishTab) { return(false); } _previewSrc = UpdateEpubControlContent(); } catch (ApplicationException ex) { if (i >= 2) { throw; } ReportProgress("Something went wrong, trying again"); continue; } break; // normal case, no exception } lock (_epubMakerLock) { if (EpubMaker.AbortRequested) { return(false); // the code that set the abort flag will request a new preview. } } } finally { lock (_epubMakerLock) { _stagingEpub = false; } } // Do pending save if the user requested it while the preview was still in progress. SaveAsEpub(); ReportProgress(LocalizationManager.GetString("PublishTab.Epub.Done", "Done")); return(true); }
public bool UpdatePreview(EpubPublishUiSettings newSettings, bool force, WebSocketProgress progress = null) { _progress = progress ?? _standardProgress.WithL10NPrefix("PublishTab.Epub."); if (Program.RunningOnUiThread) { // There's some stuff inside this lock that has to run on the UI thread. // If we lock the UI thread here, we can deadlock the whole program. throw new ApplicationException(@"Must not attempt to make epubs on UI thread...will produce deadlocks"); } lock (_epubMakerLock) { if (EpubMaker != null) { EpubMaker.AbortRequested = false; } _stagingEpub = true; } try { _webSocketServer.SendString(kWebsocketContext, "startingEbookCreation", _previewSrc); var htmlPath = _bookSelection.CurrentSelection.GetPathHtmlFile(); var newVersion = Book.Book.MakeVersionCode(File.ReadAllText(htmlPath), htmlPath); bool previewIsAlreadyCurrent; lock (_epubMakerLock) { previewIsAlreadyCurrent = _desiredEpubSettings == newSettings && EpubMaker != null && newVersion == _bookVersion && !EpubMaker.AbortRequested && !force; } if (previewIsAlreadyCurrent) { SaveAsEpub(); // just in case there's a race condition where we haven't already saved it. return(true); // preview is already up to date. } _desiredEpubSettings = newSettings; // clear the obsolete preview, if any; this also ensures that when the new one gets done, // we will really be changing the src attr in the preview iframe so the display will update. _webSocketServer.SendEvent(kWebsocketContext, kWebsocketEventId_epubReady); _bookVersion = newVersion; ReportProgress(LocalizationManager.GetString("PublishTab.Epub.PreparingPreview", "Preparing Preview")); // This three-tries loop is an attempt to recover from a weird state the system sometimes gets into // where a browser won't navigate to a temporary page that the EpubMaker uses. I'm not sure it actually // helps, once the system gets into this state even a brand new browser seems to have the same problem. // Usually there will be no exception, and the loop breaks at the end of the first iteration. for (int i = 0; i < 3; i++) { try { if (!PublishHelper.InPublishTab) { return(false); } _previewSrc = UpdateEpubControlContent(); } catch (ApplicationException ex) { if (i >= 2) { throw; } ReportProgress("Something went wrong, trying again"); continue; } break; // normal case, no exception } lock (_epubMakerLock) { if (EpubMaker.AbortRequested) { return(false); // the code that set the abort flag will request a new preview. } } } finally { lock (_epubMakerLock) { _stagingEpub = false; } } // Do pending save if the user requested it while the preview was still in progress. SaveAsEpub(); ReportProgress(LocalizationManager.GetString("PublishTab.Epub.Done", "Done")); return(true); }