Beispiel #1
0
 public void RegisterWithApiHandler(BloomApiHandler apiHandler)
 {
     apiHandler.RegisterEndpointLegacy(kApiUrlPart + "checkAutoSegmentDependencies", CheckAutoSegmentDependenciesMet, handleOnUiThread: false, requiresSync: false);
     apiHandler.RegisterEndpointLegacy(kApiUrlPart + "autoSegmentAudio", AutoSegment, handleOnUiThread: false, requiresSync: false);
     apiHandler.RegisterEndpointLegacy(kApiUrlPart + "getForcedAlignmentTimings", GetForcedAlignmentTimings, handleOnUiThread: false, requiresSync: false);
     apiHandler.RegisterEndpointLegacy(kApiUrlPart + "eSpeakPreview", ESpeakPreview, handleOnUiThread: false, requiresSync: false);
 }
Beispiel #2
0
 public void RegisterWithApiHandler(BloomApiHandler apiHandler)
 {
     // Both of these display UI, expect to require UI thread.
     apiHandler.RegisterEndpointLegacy("addPage", HandleAddPage, true).Measureable("Add Page");
     apiHandler.RegisterEndpointLegacy("changeLayout", HandleChangeLayout, true).Measureable("Change Layout");
     ;
 }
Beispiel #3
0
        public void RegisterWithApiHandler(BloomApiHandler apiHandler)
        {
            // HandleStartRecording seems to need to be on the UI thread in order for HandleEndRecord() to detect the correct state.
            apiHandler.RegisterEndpointLegacy("audio/startRecord", HandleStartRecording, true).Measureable();

            // Note: This handler locks and unlocks a shared resource (_completeRecording lock).
            // Any other handlers depending on this resource should not wait on the same thread (i.e. the UI thread) or deadlock can occur.
            apiHandler.RegisterEndpointLegacy("audio/endRecord", HandleEndRecord, true).Measureable();

            // Any handler which retrieves information from the audio folder SHOULD wait on the _completeRecording lock (call WaitForRecordingToComplete()) to ensure that it sees
            // a consistent state of the audio folder, and therefore should NOT run on the UI thread.
            // Also, explicitly setting requiresSync to true (even tho that's default anyway) to make concurrency less complicated to think about
            apiHandler.RegisterEndpointLegacy("audio/checkForAnyRecording", HandleCheckForAnyRecording, false, true);
            apiHandler.RegisterEndpointLegacy("audio/checkForAllRecording", HandleCheckForAllRecording, false, true);
            apiHandler.RegisterEndpointLegacy("audio/deleteSegment", HandleDeleteSegment, false, true);
            apiHandler.RegisterEndpointLegacy("audio/checkForSegment", HandleCheckForSegment, false, true);
            apiHandler.RegisterEndpointLegacy("audio/wavFile", HandleAudioFileRequest, false, true);

            // Doesn't matter whether these are on UI thread or not, so using the old default which was true
            apiHandler.RegisterEndpointLegacy("audio/currentRecordingDevice", HandleCurrentRecordingDevice, true);
            apiHandler.RegisterEndpointLegacy("audio/devices", HandleAudioDevices, true);

            apiHandler.RegisterEndpointLegacy("audio/copyAudioFile", HandleCopyAudioFile, false);

            Debug.Assert(BloomServer.portForHttp > 0, "Need the server to be listening before this can be registered (BL-3337).");
        }
 public void RegisterWithApiHandler(BloomApiHandler apiHandler)
 {
     apiHandler.RegisterEndpointLegacy("signLanguage/recordedVideo", HandleRecordedVideoRequest, true).Measureable("Process recorded video");
     apiHandler.RegisterEndpointLegacy("signLanguage/deleteVideo", HandleDeleteVideoRequest, true).Measureable("Delete video");;
     apiHandler.RegisterEndpointLegacy("signLanguage/importVideo", HandleImportVideoRequest, true);             // has dialog, so measure internally after the dialog.
     apiHandler.RegisterEndpointLegacy("signLanguage/getStats", HandleVideoStatisticsRequest, true);
 }
Beispiel #5
0
 public void RegisterWithApiHandler(BloomApiHandler apiHandler)
 {
     // We could probably get away with using the server thread here, but the code interacts quite a bit with the
     // current book and other state.
     apiHandler.RegisterEndpointLegacy("pageTemplates", HandleTemplatesRequest, true);
     // Being on the UI thread causes a deadlock on Linux/Mono.  See https://silbloom.myjetbrains.com/youtrack/issue/BL-3818.
     apiHandler.RegisterEndpointLegacy("pageTemplateThumbnail", HandleThumbnailRequest, false);
 }
 public void RegisterWithApiHandler(BloomApiHandler apiHandler)
 {
     // Must not require sync, because it launches a Bloom dialog, which will make other api requests
     // that will be blocked if this is locked.
     apiHandler.RegisterEndpointHandler("bookCommand/exportToSpreadsheet",
                                        (request) =>
     {
         _spreadsheetApi.ShowExportToSpreadsheetUI(GetBookObjectFromPost(request));
         request.PostSucceeded();
     }, true, false);
     apiHandler.RegisterEndpointHandler("bookCommand/enhanceLabel", (request) =>
     {
         // We want this to be fast...many things are competing for api handling threads while
         // Bloom is starting up, including many buttons sending this request...
         // so we'll postpone until idle even searching for the right BookInfo.
         var collection = request.RequiredParam("collection-id").Trim();
         var id         = request.RequiredParam("id");
         RequestButtonLabelUpdate(collection, id);
         request.PostSucceeded();
     }, false, false);
     apiHandler.RegisterBooleanEndpointHandler("bookCommand/decodable",
                                               request => { return(_collectionModel.IsBookDecodable); },
                                               (request, b) => { _collectionModel.SetIsBookDecodable(b); },
                                               true);
     apiHandler.RegisterBooleanEndpointHandler("bookCommand/leveled",
                                               request => { return(_collectionModel.IsBookLeveled); },
                                               (request, b) => { _collectionModel.SetIsBookLeveled(b); },
                                               true);
     apiHandler.RegisterEndpointLegacy("bookCommand/", HandleBookCommand, true);
 }
Beispiel #7
0
        public void RegisterWithApiHandler(BloomApiHandler apiHandler)
        {
            // Note: all book commands, including import and export spreadsheets,
            // go through a single "bookCommand/" API, so we don't register that here.
            // Instead all we need to register is any api enpoints used by our own spreadsheet dialogs

            apiHandler.RegisterEndpointLegacy("spreadsheet/export", ExportToSpreadsheet, true);
        }
Beispiel #8
0
 public static void RegisterWithApiHandler(BloomApiHandler apiHandler)
 {
     apiHandler.RegisterEndpointLegacy("help/.*", (request) =>
     {
         var topic = request.LocalPath().Replace("api/help", "");
         Show(Application.OpenForms.Cast <Form>().Last(), topic);
         //if this is called from a simple html anchor, we don't want the browser to do anything
         request.ExternalLinkSucceeded();
     }, true);             // opening a form, definitely UI thread
 }
Beispiel #9
0
 public void RegisterWithApiHandler(BloomApiHandler apiHandler)
 {
     apiHandler.RegisterEndpointLegacy("dialog/close",
                                       (ApiRequest request) =>
     {
         // Closes the current dialog.
         BrowserDialog.CloseDialog();
         request.PostSucceeded();
     }, true);
 }
Beispiel #10
0
 public void RegisterWithApiHandler(BloomApiHandler apiHandler)
 {
     apiHandler.RegisterEndpointLegacy("performance/showCsvFile", (request) =>
     {
         Process.Start(_csvFilePath);
         request.PostSucceeded();
     }, false);
     apiHandler.RegisterEndpointLegacy("performance/applicationInfo", (request) =>
     {
         request.ReplyWithText($"Bloom {Shell.GetShortVersionInfo()} {ApplicationUpdateSupport.ChannelName}");
     }, false);
     apiHandler.RegisterEndpointLegacy("performance/allMeasurements", (request) =>
     {
         List <object> l = new List <object>();
         foreach (var measurement in _measurements)
         {
             l.Add(measurement.GetSummary());
         }
         request.ReplyWithJson(l.ToArray());
     }, false);
 }
 public void RegisterWithApiHandler(BloomApiHandler apiHandler)
 {
     apiHandler.RegisterEndpointLegacy("keyboarding/useLongpress", (ApiRequest request) =>
     {
         try
         {
             //detect if some keyboarding system is active, e.g. KeyMan. If it is, don't enable LongPress
             var form = Application.OpenForms.Cast <Form>().Last();
             request.ReplyWithText(SIL.Windows.Forms.Keyboarding.KeyboardController.IsFormUsingInputProcessor(form)
                                         ? "false"
                                         : "true");
         }
         catch (Exception error)
         {
             request.ReplyWithText("true");                     // This is arbitrary. I don't know if it's better to assume keyman, or not.
             NonFatalProblem.Report(ModalIf.None, PassiveIf.All, "Error checking for keyman", "", error);
         }
     }, handleOnUiThread: false);
 }
Beispiel #12
0
        public void RegisterWithApiHandler(BloomApiHandler apiHandler)
        {
            apiHandler.RegisterEndpointLegacy("pageList/pages", HandlePagesRequest, false).Measureable();
            apiHandler.RegisterEndpointLegacy("pageList/pageContent", HandlePageContentRequest, false);
            apiHandler.RegisterEndpointLegacy("pageList/pageMoved", HandlePageMovedRequest, true).Measureable();
            apiHandler.RegisterEndpointLegacy("pageList/pageClicked", HandlePageClickedRequest, true);
            apiHandler.RegisterEndpointLegacy("pageList/menuClicked", HandleShowMenuRequest, true).Measureable();

            apiHandler.RegisterEndpointLegacy("pageList/bookAttributesThatMayAffectDisplay", (request) =>
            {
                var attrs = _bookSelection.CurrentSelection.OurHtmlDom.GetBodyAttributesThatMayAffectDisplay();
                // Surely there's a way to do this more safely with JSON.net but I haven't found it yet
                var props = string.Join(",", attrs.Select(a => ("\"" + a.Name + "\": \"" + a.Value.Replace("\"", "\\\"") + "\"")));
                request.ReplyWithJson("{" + props + "}");
            }, true);
        }
Beispiel #13
0
        public void RegisterWithApiHandler(BloomApiHandler apiHandler)
        {
            bool requiresSync = false;             // Lets us open the dialog while the epub preview is being generated

            apiHandler.RegisterEndpointLegacy("book/metadata", HandleBookMetadata, false, requiresSync);
        }
Beispiel #14
0
 public void RegisterWithApiHandler(BloomApiHandler apiHandler)
 {
     apiHandler.RegisterEndpointLegacy("fileIO/chooseFile", ChooseFile, true);
     apiHandler.RegisterEndpointLegacy("fileIO/getSpecialLocation", GetSpecialLocation, true);
     apiHandler.RegisterEndpointLegacy("fileIO/copyFile", CopyFile, true);
 }
Beispiel #15
0
 public void RegisterWithApiHandler(BloomApiHandler apiHandler)
 {
     apiHandler.RegisterEndpointLegacy("toolbox/enabledTools", HandleEnabledToolsRequest, true);
     apiHandler.RegisterEndpointLegacy("toolbox/fileExists", HandleFileExistsRequest, true);
 }
Beispiel #16
0
        public void RegisterWithApiHandler(BloomApiHandler apiHandler)
        {
            apiHandler.RegisterEndpointLegacy("uiLanguages", HandleUiLanguages, false);                               // App
            apiHandler.RegisterEndpointLegacy("currentUiLanguage", HandleCurrentUiLanguage, false);                   // App
            apiHandler.RegisterEndpointLegacy("bubbleLanguages", HandleBubbleLanguages, false);                       // Move to EditingViewApi
            apiHandler.RegisterEndpointLegacy("authorMode", HandleAuthorMode, false);                                 // Move to EditingViewApi
            apiHandler.RegisterEndpointLegacy("topics", HandleTopics, false);                                         // Move to EditingViewApi
            apiHandler.RegisterEndpointLegacy("common/error", HandleJavascriptError, false);                          // Common
            apiHandler.RegisterEndpointLegacy("common/preliminaryError", HandlePreliminaryJavascriptError, false);    // Common
            apiHandler.RegisterEndpointLegacy("common/saveChangesAndRethinkPageEvent", RethinkPageAndReloadIt, true); // Move to EditingViewApi
            apiHandler.RegisterEndpointLegacy("common/chooseFolder", HandleChooseFolder, true);
            apiHandler.RegisterEndpointLegacy("common/showInFolder", HandleShowInFolderRequest, true);                // Common
            apiHandler.RegisterEndpointLegacy("common/canModifyCurrentBook", HandleCanModifyCurrentBook, true);
            apiHandler.RegisterEndpointLegacy("common/showSettingsDialog", HandleShowSettingsDialog, false);          // Common
            apiHandler.RegisterEndpointLegacy("common/problemWithBookMessage", request =>
            {
                request.ReplyWithText(CommonMessages.GetProblemWithBookMessage(Path.GetFileName(_bookSelection.CurrentSelection?.FolderPath)));
            }, false);
            apiHandler.RegisterEndpointLegacy("common/clickHereForHelp", request =>
            {
                var problemFilePath = UrlPathString.CreateFromUrlEncodedString(request.RequiredParam("problem")).NotEncoded;
                request.ReplyWithText(CommonMessages.GetPleaseClickHereForHelpMessage(problemFilePath));
            }, false);
            // Used when something in JS land wants to copy text to or from the clipboard. For POST, the text to be put on the
            // clipboard is passed as the 'text' property of a JSON requestData.
            // Somehow the get version of this fires while initializing a page (probably hooking up CkEditor, an unwanted
            // invocation of the code that decides whether to enable the paste hyperlink button). This causes a deadlock
            // unless we make this endpoint requiresSync:false. I think this is safe as it doesn't interact with any other
            // Bloom objects.
            apiHandler.RegisterEndpointLegacy("common/clipboardText",
                                              request =>
            {
                if (request.HttpMethod == HttpMethods.Get)
                {
                    string result = "";                             // initial value is not used, delegate will set it.
                    Program.MainContext.Send(o =>
                    {
                        try
                        {
                            result = PortableClipboard.GetText();
                        }
                        catch (Exception e)
                        {
                            // Need to make sure to handle exceptions.
                            // If the worker thread dies with an unhandled exception,
                            // it causes the whole program to immediately crash without opportunity for error reporting
                            NonFatalProblem.Report(ModalIf.All, PassiveIf.None, "Error pasting text", exception: e);
                        }
                    }, null);
                    request.ReplyWithText(result);
                }
                else
                {
                    // post
                    var requestData = DynamicJson.Parse(request.RequiredPostJson());
                    string content  = requestData.text;
                    if (!string.IsNullOrEmpty(content))
                    {
                        Program.MainContext.Post(o =>
                        {
                            try
                            {
                                PortableClipboard.SetText(content);
                            }
                            catch (Exception e)
                            {
                                // Need to make sure to handle exceptions.
                                // If the worker thread dies with an unhandled exception,
                                // it causes the whole program to immediately crash without opportunity for error reporting
                                NonFatalProblem.Report(ModalIf.All, PassiveIf.None, "Error copying text", exception: e);
                            }
                        }, null);
                    }
                    request.PostSucceeded();
                }
            }, false, false);
            apiHandler.RegisterEndpointLegacy("common/checkForUpdates",
                                              request =>
            {
                WorkspaceView.CheckForUpdates();
                request.PostSucceeded();
            }, false);
            apiHandler.RegisterEndpointLegacy("common/channel",
                                              request =>
            {
                request.ReplyWithText(ApplicationUpdateSupport.ChannelName);
            }, false);
            // This is useful for debugging TypeScript code, especially on Linux.  I wouldn't necessarily expect
            // to see it used anywhere in code that gets submitted and merged.
            apiHandler.RegisterEndpointLegacy("common/debugMessage",
                                              request =>
            {
                var message = request.RequiredPostString();
                Debug.WriteLine("FROM JS: " + message);
                request.PostSucceeded();
            }, false);

            apiHandler.RegisterEndpointLegacy("common/loginData",
                                              request =>
            {
                var requestData = DynamicJson.Parse(request.RequiredPostJson());
                string token    = requestData.sessionToken;
                string email    = requestData.email;
                string userId   = requestData.userId;
                //Debug.WriteLine("Got login data " + email + " with token " + token + " and id " + userId);
                _parseClient.SetLoginData(email, userId, token, BookUpload.Destination);
                _doWhenLoggedIn?.Invoke();
                request.PostSucceeded();
            }, false);

            // At this point we open dialogs from c# code; if we opened dialogs from javascript, we wouldn't need this
            // api to do it. We just need a way to close a c#-opened dialog from javascript (e.g. the Close button of the dialog).
            //
            // This must set requiresSync:false because the API call which opened the dialog may already have
            // the lock in which case we would be deadlocked.
            // ErrorReport.NotifyUserOfProblem is a particularly problematic case. We tried to come up with some
            // other solutions for that including opening the dialog on Application.Idle. But the dialog needs
            // to give a real-time result so callers can know what do with button presses. Since some of those
            // callers are in libpalaso, we can't just ignore the result and handle the actions ourselves.
            apiHandler.RegisterEndpointLegacy("common/closeReactDialog", request =>
            {
                ReactDialog.CloseCurrentModal(request.GetPostStringOrNull());
                request.PostSucceeded();
            }, true, requiresSync: false);

            // TODO: move to the new App API (BL-9635)
            apiHandler.RegisterEndpointLegacy("common/reloadCollection", HandleReloadCollection, true);
        }
Beispiel #17
0
        public void RegisterWithApiHandler(BloomApiHandler apiHandler)
        {
            apiHandler.RegisterEndpointLegacy(kApiUrlPart + "bookName", request =>
            {
                request.ReplyWithText(request.CurrentBook.NameBestForUserDisplay);
            }, false);

            apiHandler.RegisterEndpointLegacy(kApiUrlPart + "showAccessibilityChecker", request =>
            {
                AccessibilityCheckWindow.StaticShow(() => _webSocketServer.SendEvent(kWebSocketContext, kWindowActivated));
                request.PostSucceeded();
            }, true);

            apiHandler.RegisterEndpointLegacy(kApiUrlPart + "descriptionsForAllImages", request =>
            {
                var problems    = AccessibilityCheckers.CheckDescriptionsForAllImages(request.CurrentBook);
                var resultClass = problems.Any() ? "failed" : "passed";
                request.ReplyWithJson(new { resultClass = resultClass, problems = problems });
            }, false);

            apiHandler.RegisterEndpointLegacy(kApiUrlPart + "audioForAllImageDescriptions", request =>
            {
                var problems    = AccessibilityCheckers.CheckAudioForAllImageDescriptions(request.CurrentBook);
                var resultClass = problems.Any() ? "failed" : "passed";
                request.ReplyWithJson(new { resultClass = resultClass, problems = problems });
            }, false);

            apiHandler.RegisterEndpointLegacy(kApiUrlPart + "audioForAllText", request =>
            {
                var problems    = AccessibilityCheckers.CheckAudioForAllText(request.CurrentBook);
                var resultClass = problems.Any() ? "failed" : "passed";
                request.ReplyWithJson(new { resultClass = resultClass, problems = problems });
            }, false);

            // Just a checkbox that the user ticks to say "yes, I checked this"
            // At this point, we don't have a way to clear that when the book changes.
            apiHandler.RegisterBooleanEndpointHandler(kApiUrlPart + "noEssentialInfoByColor",
                                                      request => request.CurrentBook.BookInfo.MetaData.A11y_NoEssentialInfoByColor,
                                                      (request, b) => {
                request.CurrentBook.BookInfo.MetaData.A11y_NoEssentialInfoByColor = b;
                request.CurrentBook.Save();
            },
                                                      false);

            // Just a checkbox that the user ticks to say "yes, I checked this"
            // At this point, we don't have a way to clear that when the book changes.
            apiHandler.RegisterBooleanEndpointHandler(kApiUrlPart + "noTextIncludedInAnyImages",
                                                      request => request.CurrentBook.BookInfo.MetaData.A11y_NoTextIncludedInAnyImages,
                                                      (request, b) => {
                request.CurrentBook.BookInfo.MetaData.A11y_NoTextIncludedInAnyImages = b;
                request.CurrentBook.Save();
            },
                                                      false);

            //enhance: this might have to become async to work on large books on slow computers
            apiHandler.RegisterEndpointLegacy(kApiUrlPart + "aceByDaisyReportUrl", request => { MakeAceByDaisyReport(request); },
                                              false, false
                                              );

            // A checkbox that the user ticks in the Accessible Image tool to request a preview
            // of how things might look with cataracts.
            // For now this doesn't seem worth persisting, except for the session so it sticks from page to page.
            apiHandler.RegisterBooleanEndpointHandler(kApiUrlPart + "cataracts",
                                                      request => _simulateCataracts,
                                                      (request, b) => { _simulateCataracts = b; },
                                                      false);
            // A checkbox that the user ticks in the Accessible Image tool to request a preview
            // of how things might look with color-blindness, and a set of radio buttons
            // for choosing different kinds of color-blindness.
            // For now these doesn't seem worth persisting, except for the session so it sticks from page to page.
            apiHandler.RegisterBooleanEndpointHandler(kApiUrlPart + "colorBlindness",
                                                      request => _simulateColorBlindness,
                                                      (request, b) => { _simulateColorBlindness = b; },
                                                      false);
            apiHandler.RegisterEnumEndpointHandler(kApiUrlPart + "kindOfColorBlindness",
                                                   request => _kindOfColorBlindness,
                                                   (request, kind) => _kindOfColorBlindness = kind, false);
        }
Beispiel #18
0
 public void RegisterWithApiHandler(BloomApiHandler apiHandler)
 {
     apiHandler.RegisterEndpointLegacy("editView/setModalState", HandleSetModalState, true);
     apiHandler.RegisterEndpointLegacy("editView/chooseWidget", HandleChooseWidget, true);
     apiHandler.RegisterEndpointLegacy("editView/getBookColors", HandleGetColors, true);
     apiHandler.RegisterEndpointLegacy("editView/editPagePainted", HandleEditPagePainted, true);
     apiHandler.RegisterEndpointLegacy("editView/saveToolboxSetting", HandleSaveToolboxSetting, true);
     apiHandler.RegisterEndpointLegacy("editView/setTopic", HandleSetTopic, true);
     apiHandler.RegisterEndpointLegacy("editView/isTextSelected", HandleIsTextSelected, false);
     apiHandler.RegisterEndpointLegacy("editView/getBookLangs", HandleGetBookLangs, false);
     apiHandler.RegisterEndpointLegacy("editView/isClipboardBookHyperlink", HandleIsClipboardBookHyperlink, false);
     apiHandler.RegisterEndpointLegacy("editView/requestTranslationGroupContent", RequestDefaultTranslationGroupContent, true);
     apiHandler.RegisterEndpointLegacy("editView/duplicatePageMany", HandleDuplicatePageMany, true);
 }
 public void RegisterWithApiHandler(BloomApiHandler apiHandler)
 {
     apiHandler.RegisterEndpointLegacy("progress/cancel", Cancel, false, false);
 }
 public void RegisterWithApiHandler(BloomApiHandler apiHandler)
 {
     apiHandler.RegisterEndpointLegacy("libraryPublish/upload", HandleUpload, true);
     apiHandler.RegisterEndpointLegacy("libraryPublish/cancel", HandleCancel, true);
 }
Beispiel #21
0
        public void RegisterWithApiHandler(BloomApiHandler apiHandler)
        {
            apiHandler.RegisterEndpointLegacy(kApiUrlPart + "requestState", request =>
            {
                if (request.HttpMethod == HttpMethods.Get)
                {
                    request.ReplyWithJson(CurrentStateString);
                }
                else                 // post
                {
                    Debug.Fail("We shouldn't ever be using the 'post' version.");
                    request.PostSucceeded();
                }
            }, true);

            apiHandler.RegisterEndpointLegacy(kApiUrlPart + "addPage", request =>
            {
                AddPageButton_Click();
                request.PostSucceeded();
            }, true).Measureable();

            apiHandler.RegisterEndpointLegacy(kApiUrlPart + "duplicatePage", request =>
            {
                _editingModel.OnDuplicatePage();
                request.PostSucceeded();
            }, true).Measureable();

            apiHandler.RegisterEndpointLegacy(kApiUrlPart + "deletePage", request =>
            {
                if (ConfirmRemovePageDialog.Confirm())
                {
                    _editingModel.OnDeletePage();
                }
                request.PostSucceeded();
            }, true).Measureable();

            apiHandler.RegisterEndpointLegacy(kApiUrlPart + "lockBook", request =>
            {
                _editingModel.SaveNow();                 // BL-5421 lock and unlock lose typing
                _editingModel.CurrentBook.TemporarilyUnlocked = false;
                request.PostSucceeded();
                UpdateState();                 // because we aren't selecting a new page
                _editingModel.RefreshDisplayOfCurrentPage();
            }, true);

            apiHandler.RegisterEndpointLegacy(kApiUrlPart + "unlockBook", request =>
            {
                _editingModel.SaveNow();                 // BL-5421 lock and unlock lose typing
                _editingModel.CurrentBook.TemporarilyUnlocked = true;
                request.PostSucceeded();
                UpdateState();                 // because we aren't selecting a new page
                _editingModel.RefreshDisplayOfCurrentPage();
            }, true);

            apiHandler.RegisterEndpointLegacy(kApiUrlPart + "cleanup", request =>
            {
                SendCleanupState();
                request.PostSucceeded();
            }, true);

            apiHandler.RegisterEndpointLegacy(kApiUrlPart + "zoomMinus", request =>
            {
                _editingModel.AdjustPageZoom(-10);
                request.PostSucceeded();
            }, true);

            apiHandler.RegisterEndpointLegacy(kApiUrlPart + "zoomPlus", request =>
            {
                _editingModel.AdjustPageZoom(10);
                request.PostSucceeded();
            }, true);

            apiHandler.RegisterEndpointLegacy(kApiUrlPart + "requestVideoPlaceHolder", request =>
            {
                _editingModel.RequestVideoPlaceHolder();
                request.PostSucceeded();
            }, true);

            apiHandler.RegisterEndpointLegacy(kApiUrlPart + "requestWidgetPlaceHolder", request =>
            {
                _editingModel.RequestWidgetPlaceHolder();
                request.PostSucceeded();
            }, true);
        }
Beispiel #22
0
 public static void RegisterWithApiHandler(BloomApiHandler apiHandler)
 {
     // Opening a page, better be in UI thread.
     apiHandler.RegisterEndpointLegacy(kPrefix + "/.*", HandleRequest, true);
 }
Beispiel #23
0
 public void RegisterWithApiHandler(BloomApiHandler apiHandler)
 {
     apiHandler.RegisterEndpointLegacy("music/ui/chooseFile", HandleRequest, true);
 }
Beispiel #24
0
        public void RegisterWithApiHandler(BloomApiHandler apiHandler)
        {
            apiHandler.RegisterEndpointHandler(kApiUrlPart + "save", HandleEpubSave, true, false);

            apiHandler.RegisterEndpointLegacy(kApiUrlPart + "epubSettings", request =>
            {
                if (request.HttpMethod == HttpMethods.Get)
                {
                    request.ReplyWithJson(GetEpubSettings());
                }
                else
                {
                    // post is deprecated.
                    throw new ApplicationException("epubSettings POST is deprecated");
                }
            }, false);

            // The backend here was written with an enum that had two choices for how to publish descriptions, but we only ever
            // have used one of them so far in the UI. So this is a boolean api that converts to an enum underlying value.
            apiHandler.RegisterBooleanEndpointHandler(kApiUrlPart + "imageDescriptionSetting",
                                                      request => request.CurrentBook.BookInfo.PublishSettings.Epub.HowToPublishImageDescriptions == BookInfo.HowToPublishImageDescriptions.OnPage,
                                                      (request, onPage) =>
            {
                request.CurrentBook.BookInfo.PublishSettings.Epub.HowToPublishImageDescriptions = onPage
                                                ? BookInfo.HowToPublishImageDescriptions.OnPage
                                                : BookInfo.HowToPublishImageDescriptions.None;
                request.CurrentBook.BookInfo.Save();
                var newSettings = _desiredEpubSettings.Clone();
                newSettings.howToPublishImageDescriptions = request.CurrentBook.BookInfo.PublishSettings.Epub.HowToPublishImageDescriptions;
                RefreshPreview(newSettings);
            },
                                                      false);

            // Saving a checkbox setting that the user ticks to say "Use my E-reader's font sizes"
            apiHandler.RegisterBooleanEndpointHandler(kApiUrlPart + "removeFontSizesSetting",
                                                      request => request.CurrentBook.BookInfo.PublishSettings.Epub.RemoveFontSizes,
                                                      (request, booleanSetting) => {
                request.CurrentBook.BookInfo.PublishSettings.Epub.RemoveFontSizes = booleanSetting;
                request.CurrentBook.BookInfo.Save();
                var newSettings             = _desiredEpubSettings.Clone();
                newSettings.removeFontSizes = booleanSetting;
                RefreshPreview(newSettings);
            },
                                                      false);

            apiHandler.RegisterEndpointLegacy(kApiUrlPart + "updatePreview", request =>
            {
                RefreshPreview(_desiredEpubSettings);
                request.PostSucceeded();
                if (request.CurrentBook?.ActiveLanguages != null)
                {
                    var message = new LicenseChecker().CheckBook(request.CurrentBook, request.CurrentBook.ActiveLanguages.ToArray());
                    _webSocketServer.SendString(kWebsocketContext, kWebsocketState_LicenseOK, (message == null) ? "true" : "false");
                }
            }, false);             // in fact, must NOT be on UI thread

            apiHandler.RegisterEndpointLegacy(kApiUrlPart + "abortPreview", request =>
            {
                AbortMakingEpub();

                request.PostSucceeded();
            }, false, false);
        }
Beispiel #25
0
        private static IEnumerable <string> _additionalPathsToInclude;          // typically a problem image file

        public void RegisterWithApiHandler(BloomApiHandler apiHandler)
        {
            // This one is an exception: it's not used BY the problem report dialog, but to launch one
            // from Javascript. However, it also must not require the lock, because if it holds it,
            // no calls that need it can run (such as one put forth by the Cancel button).
            apiHandler.RegisterEndpointLegacy("problemReport/showDialog", HandleShowDialog, true, false);
            // Similarly, but this launches from a button shown in Book.ErrorDom
            apiHandler.RegisterEndpointHandler("problemReport/unreadableBook", HandleUnreadableBook, true, false);

            // For the paranoid - We could also have showProblemReport block these handlers while _reportInfo is being populated.
            // I think it's unnecessary since the problem report dialog's URL isn't even set until after the _reportInfo is populated,
            // and we assume that nothing sends problemReport API requests except the problemReportDialog that this class loads.

            // ProblemDialog.tsx uses this endpoint to get the string to show at the top of the main dialog
            apiHandler.RegisterEndpointHandlerUsedByOthers("problemReport/reportHeadingHtml",
                                                           (ApiRequest request) =>
            {
                request.ReplyWithText(_reportInfo.HeadingHtml ?? "");
            }, false);
            // ProblemDialog.tsx uses this endpoint to get the screenshot image.
            apiHandler.RegisterEndpointHandlerUsedByOthers("problemReport/screenshot",
                                                           (ApiRequest request) =>
            {
                // Wait until the screenshot is finished.
                // If not available within the time limit, just continue anyway (so we don't deadlock or anything) and hope for the best.
                bool isLockTaken = _takingScreenshotLock.Wait(millisecondsTimeout: 5000);

                if (_reportInfo?.ScreenshotTempFile == null)
                {
                    request.Failed();
                }
                else
                {
                    request.ReplyWithImage(_reportInfo.ScreenshotTempFile.Path);
                }

                if (isLockTaken)
                {
                    _takingScreenshotLock.Release();
                }
            }, true);

            // ProblemDialog.tsx uses this endpoint to get the name of the book.
            apiHandler.RegisterEndpointHandlerUsedByOthers("problemReport/bookName",
                                                           (ApiRequest request) =>
            {
                request.ReplyWithText(_reportInfo.BookName ?? "??");
            }, true);

            // ProblemDialog.tsx uses this endpoint to get the registered user's email address.
            apiHandler.RegisterEndpointHandlerUsedByOthers("problemReport/emailAddress",
                                                           (ApiRequest request) =>
            {
                request.ReplyWithText(_reportInfo.UserEmail);
            }, true);

            // PrivacyScreen.tsx uses this endpoint to show the user what info will be included in the report.
            apiHandler.RegisterEndpointHandlerUsedByOthers("problemReport/diagnosticInfo",
                                                           (ApiRequest request) =>
            {
                var userWantsToIncludeBook = request.RequiredParam("includeBook") == "true";
                var userInput = request.RequiredParam("userInput");
                var userEmail = request.RequiredParam("email");
                request.ReplyWithText(GetDiagnosticInfo(userWantsToIncludeBook, userInput, userEmail));
            }, true);

            // ProblemDialog.tsx uses this endpoint in its AttemptSubmit method;
            // it expects a response that it will use to show the issue link to the user.
            apiHandler.RegisterEndpointHandlerUsedByOthers("problemReport/submit",
                                                           (ApiRequest request) =>
            {
                var report = DynamicJson.Parse(request.RequiredPostJson());

                string issueLink = SubmitToYouTrack(report.kind, report.userInput, report.email, report.includeBook, report.includeScreenshot, null);

                object linkToNewIssue = new { issueLink };
                request.ReplyWithJson(linkToNewIssue);
            }, true);
        }
Beispiel #26
0
 public static void RegisterWithApiHandler(BloomApiHandler apiHandler)
 {
     apiHandler.RegisterEndpointLegacy("toolbox/settings", HandleSettings, false);
 }
        public void RegisterWithApiHandler(BloomApiHandler apiHandler)
        {
            // This is just for storing the user preference of method
            // If we had a couple of these, we could just have a generic preferences api
            // that browser-side code could use.
            apiHandler.RegisterEndpointLegacy(kApiUrlPart + "method", request =>
            {
                if (request.HttpMethod == HttpMethods.Get)
                {
                    var method = Settings.Default.PublishAndroidMethod;
                    if (!new string[] { "wifi", "usb", "file" }.Contains(method))
                    {
                        method = "wifi";
                    }
                    request.ReplyWithText(method);
                }
                else                 // post
                {
                    Settings.Default.PublishAndroidMethod = request.RequiredPostString();
#if __MonoCS__
                    if (Settings.Default.PublishAndroidMethod == "usb")
                    {
                        _progress.MessageWithoutLocalizing("Sorry, this method is not available on Linux yet.");
                    }
#endif
                    request.PostSucceeded();
                }
            }, true);

            apiHandler.RegisterEndpointLegacy(kApiUrlPart + "backColor", request =>
            {
                if (request.HttpMethod == HttpMethods.Get)
                {
                    if (request.CurrentBook != _coverColorSourceBook)
                    {
                        _coverColorSourceBook = request.CurrentBook;
                        ImageUtils.TryCssColorFromString(request.CurrentBook?.GetCoverColor() ?? "", out _thumbnailBackgroundColor);
                    }
                    request.ReplyWithText(ToCssColorString(_thumbnailBackgroundColor));
                }
                else                 // post
                {
                    // ignore invalid colors (very common while user is editing hex)
                    Color newColor;
                    var newColorAsString = request.RequiredPostString();
                    if (ImageUtils.TryCssColorFromString(newColorAsString, out newColor))
                    {
                        _thumbnailBackgroundColor = newColor;
                        request.CurrentBook.SetCoverColor(newColorAsString);
                    }
                    request.PostSucceeded();
                }
            }, true);

            apiHandler.RegisterBooleanEndpointHandler(kApiUrlPart + "motionBookMode",
                                                      readRequest =>
            {
                // If the user has taken off all possible motion, force not having motion in the
                // Bloom Reader book.  See https://issues.bloomlibrary.org/youtrack/issue/BL-7680.
                if (!readRequest.CurrentBook.HasMotionPages)
                {
                    readRequest.CurrentBook.BookInfo.PublishSettings.BloomPub.Motion = false;
                }
                return(readRequest.CurrentBook.BookInfo.PublishSettings.BloomPub.Motion);
            },
                                                      (writeRequest, value) =>
            {
                writeRequest.CurrentBook.BookInfo.PublishSettings.BloomPub.Motion = value;
                writeRequest.CurrentBook.BookInfo.SavePublishSettings();
                _webSocketServer.SendEvent("publish", "motionChanged");
            }
                                                      , true);

            apiHandler.RegisterEndpointHandler(kApiUrlPart + "updatePreview", request =>
            {
                MakeBloompubPreview(request, false);
            }, false);


            apiHandler.RegisterEndpointLegacy(kApiUrlPart + "thumbnail", request =>
            {
                var coverImage = request.CurrentBook.GetCoverImagePath();
                if (coverImage == null)
                {
                    request.Failed("no cover image");
                }
                else
                {
                    // We don't care as much about making it resized as making its background transparent.
                    using (var thumbnail = TempFile.CreateAndGetPathButDontMakeTheFile())
                    {
                        if (_thumbnailBackgroundColor == Color.Transparent)
                        {
                            ImageUtils.TryCssColorFromString(request.CurrentBook?.GetCoverColor(), out _thumbnailBackgroundColor);
                        }
                        RuntimeImageProcessor.GenerateEBookThumbnail(coverImage, thumbnail.Path, 256, 256, _thumbnailBackgroundColor);
                        request.ReplyWithImage(thumbnail.Path);
                    }
                }
            }, true);

            apiHandler.RegisterEndpointHandler(kApiUrlPart + "usb/start", request =>
            {
#if !__MonoCS__
                SetState("UsbStarted");
                UpdatePreviewIfNeeded(request);
                _usbPublisher.Connect(request.CurrentBook, _thumbnailBackgroundColor, GetSettings());
#endif
                request.PostSucceeded();
            }, true);

            apiHandler.RegisterEndpointHandler(kApiUrlPart + "usb/stop", request =>
            {
#if !__MonoCS__
                _usbPublisher.Stop(disposing: false);
                SetState("stopped");
#endif
                request.PostSucceeded();
            }, true);
            apiHandler.RegisterEndpointLegacy(kApiUrlPart + "wifi/start", request =>
            {
                SetState("ServingOnWifi");
                UpdatePreviewIfNeeded(request);
                _wifiPublisher.Start(request.CurrentBook, request.CurrentCollectionSettings, _thumbnailBackgroundColor, GetSettings());

                request.PostSucceeded();
            }, true);

            apiHandler.RegisterEndpointLegacy(kApiUrlPart + "wifi/stop", request =>
            {
                _wifiPublisher.Stop();
                SetState("stopped");
                request.PostSucceeded();
            }, true);

            apiHandler.RegisterEndpointLegacy(kApiUrlPart + "file/save", request =>
            {
                UpdatePreviewIfNeeded(request);
                FilePublisher.Save(request.CurrentBook, _bookServer, _thumbnailBackgroundColor, _progress, GetSettings());
                SetState("stopped");
                request.PostSucceeded();
            }, true);

            apiHandler.RegisterEndpointLegacy(kApiUrlPart + "file/bulkSaveBloomPubsParams", request =>
            {
                request.ReplyWithJson(JsonConvert.SerializeObject(_collectionSettings.BulkPublishBloomPubSettings));
            }, true);

            apiHandler.RegisterEndpointLegacy(kApiUrlPart + "file/bulkSaveBloomPubs", request =>
            {
                // update what's in the collection so that we remember for next time
                _collectionSettings.BulkPublishBloomPubSettings = request.RequiredPostObject <BulkBloomPubPublishSettings>();
                _collectionSettings.Save();

                _bulkBloomPubCreator.PublishAllBooks(_collectionSettings.BulkPublishBloomPubSettings);
                SetState("stopped");
                request.PostSucceeded();
            }, true);

            apiHandler.RegisterEndpointLegacy(kApiUrlPart + "textToClipboard", request =>
            {
                PortableClipboard.SetText(request.RequiredPostString());
                request.PostSucceeded();
            }, true);

            apiHandler.RegisterBooleanEndpointHandler(kApiUrlPart + "canHaveMotionMode",
                                                      request =>
            {
                return(request.CurrentBook.HasMotionPages);
            },
                                                      null,  // no write action
                                                      false,
                                                      true); // we don't really know, just safe default

            apiHandler.RegisterBooleanEndpointHandler(kApiUrlPart + "canRotate",
                                                      request =>
            {
                return(request.CurrentBook.BookInfo.PublishSettings.BloomPub.Motion && request.CurrentBook.HasMotionPages);
            },
                                                      null,  // no write action
                                                      false,
                                                      true); // we don't really know, just safe default

            apiHandler.RegisterBooleanEndpointHandler(kApiUrlPart + "defaultLandscape",
                                                      request =>
            {
                return(request.CurrentBook.GetLayout().SizeAndOrientation.IsLandScape);
            },
                                                      null,  // no write action
                                                      false,
                                                      true); // we don't really know, just safe default
            apiHandler.RegisterEndpointLegacy(kApiUrlPart + "languagesInBook", request =>
            {
                try
                {
                    InitializeLanguagesInBook(request);

                    Dictionary <string, InclusionSetting> textLangsToPublish  = request.CurrentBook.BookInfo.PublishSettings.BloomPub.TextLangs;
                    Dictionary <string, InclusionSetting> audioLangsToPublish = request.CurrentBook.BookInfo.PublishSettings.BloomPub.AudioLangs;

                    var result = "[" + string.Join(",", _allLanguages.Select(kvp =>
                    {
                        string langCode = kvp.Key;

                        bool includeText = false;
                        if (textLangsToPublish != null && textLangsToPublish.TryGetValue(langCode, out InclusionSetting includeTextSetting))
                        {
                            includeText = includeTextSetting.IsIncluded();
                        }

                        bool includeAudio = false;
                        if (audioLangsToPublish != null && audioLangsToPublish.TryGetValue(langCode, out InclusionSetting includeAudioSetting))
                        {
                            includeAudio = includeAudioSetting.IsIncluded();
                        }

                        var value = new LanguagePublishInfo()
                        {
                            code             = kvp.Key,
                            name             = request.CurrentBook.PrettyPrintLanguage(langCode),
                            complete         = kvp.Value,
                            includeText      = includeText,
                            containsAnyAudio = _languagesWithAudio.Contains(langCode),
                            includeAudio     = includeAudio
                        };
                        var json = JsonConvert.SerializeObject(value);
                        return(json);
                    })) + "]";

                    request.ReplyWithText(result);
                }
Beispiel #28
0
 public void RegisterWithApiHandler(BloomApiHandler apiHandler)
 {
     // These are both just retrieving information about files, apart from using _bookSelection.CurrentSelection.FolderPath.
     apiHandler.RegisterEndpointLegacy("image/info", HandleImageInfo, false);
     apiHandler.RegisterEndpointLegacy("image/imageCreditsForWholeBook", HandleCopyImageCreditsForWholeBook, false);
 }