예제 #1
0
        private void HandleJoinTeamCollection(ApiRequest request)
        {
            try
            {
                FolderTeamCollection.JoinCollectionTeam();
                ReactDialog.CloseCurrentModal();

                Analytics.Track("TeamCollectionJoin",
                                new Dictionary <string, string>()
                {
                    { "CollectionId", _settings?.CollectionId },
                    { "CollectionName", _settings?.CollectionName },
                    { "Backend", _tcManager?.CurrentCollection?.GetBackendType() },
                    { "User", CurrentUser }
                });

                request.PostSucceeded();
            }
            catch (Exception e)
            {
                // Not sure what to do here: joining the collection crashed.
                Logger.WriteError("TeamCollectionApi.HandleJoinTeamCollection() crashed", e);
                var msg = LocalizationManager.GetString("TeamCollection.ErrorJoining", "Could not join Team Collection");
                ErrorReport.NotifyUserOfProblem(e, msg);
                NonFatalProblem.ReportSentryOnly(e, $"Something went wrong for {request.LocalPath()}");

                // Since we have already informed the user above, it is better to just report a success here.
                // Otherwise, they will also get a toast.
                request.PostSucceeded();
            }
        }
예제 #2
0
        public CollectionSettingsDialog(CollectionSettings collectionSettings,
                                        QueueRenameOfCollection queueRenameOfCollection, PageRefreshEvent pageRefreshEvent,
                                        TeamCollectionManager tcManager, XMatterPackFinder xmatterPackFinder)
        {
            _collectionSettings      = collectionSettings;
            _queueRenameOfCollection = queueRenameOfCollection;
            _pageRefreshEvent        = pageRefreshEvent;
            _xmatterPackFinder       = xmatterPackFinder;
            InitializeComponent();

            _language1Name.UseMnemonic = false;             // Allow & to be part of the language display names.
            _language2Name.UseMnemonic = false;             // This may be unlikely, but can't be ruled out.
            _language3Name.UseMnemonic = false;             // See https://issues.bloomlibrary.org/youtrack/issue/BL-9919.

            PendingFontSelections[0] = _collectionSettings.LanguagesZeroBased[0].FontName;
            PendingFontSelections[1] = _collectionSettings.LanguagesZeroBased[1].FontName;
            var have3rdLanguage = _collectionSettings.LanguagesZeroBased[2] != null;

            PendingFontSelections[2] = have3rdLanguage ?
                                       _collectionSettings.LanguagesZeroBased[2].FontName :
                                       "";
            PendingNumberingStyle = _collectionSettings.PageNumberStyle;
            PendingXmatter        = _collectionSettings.XMatterPackName;
            CollectionSettingsApi.DialogBeingEdited = this;

            if (_collectionSettings.IsSourceCollection)
            {
                _language1Label.Text = LocalizationManager.GetString("CollectionSettingsDialog.LanguageTab.Language1InSourceCollection", "Language 1", "In a local language collection, we say 'Local Language', but in a source collection, Local Language has no relevance, so we use this different label");
                _language2Label.Text = LocalizationManager.GetString("CollectionSettingsDialog.LanguageTab.Language2InSourceCollection", "Language 2", "In a local language collection, we say 'Language 2 (e.g. National Language)', but in a source collection, National Language has no relevance, so we use this different label");
                _language3Label.Text = LocalizationManager.GetString("CollectionSettingsDialog.LanguageTab.Language3InSourceCollection", "Language 3", "In a local language collection, we say 'Language 3 (e.g. Regional Language)', but in a source collection, National Language has no relevance, so we use this different label");
            }

            _showExperimentalBookSources.Checked  = ExperimentalFeatures.IsFeatureEnabled(ExperimentalFeatures.kExperimentalSourceBooks);
            _allowTeamCollection.Checked          = ExperimentalFeatures.IsFeatureEnabled(ExperimentalFeatures.kTeamCollections);
            _allowSpreadsheetImportExport.Checked = ExperimentalFeatures.IsFeatureEnabled(ExperimentalFeatures.kSpreadsheetImportExport);

            if (!ExperimentalFeatures.IsFeatureEnabled(ExperimentalFeatures.kTeamCollections) && tcManager.CurrentCollectionEvenIfDisconnected == null)
            {
                this._tab.Controls.Remove(this._teamCollectionTab);
            }
            // Don't allow the user to disable the Team Collection feature if we're currently in a Team Collection.
            _allowTeamCollection.Enabled = !(_allowTeamCollection.Checked && tcManager.CurrentCollectionEvenIfDisconnected != null);

            // AutoUpdate applies only to Windows: see https://silbloom.myjetbrains.com/youtrack/issue/BL-2317.
            if (SIL.PlatformUtilities.Platform.IsWindows)
            {
                _automaticallyUpdate.Checked = Settings.Default.AutoUpdate;
            }
            else
            {
                _automaticallyUpdate.Hide();
            }

            // Without this, PendingDefaultBookshelf stays null unless the user changes it.
            // The result is the bookshelf selection gets cleared when other collection settings are saved. See BL-10093.
            PendingDefaultBookshelf = _collectionSettings.DefaultBookshelf;

            CollectionSettingsApi.BrandingChangeHandler = ChangeBranding;

            TeamCollectionApi.TheOneInstance.SetCallbackToReopenCollection(() =>
            {
                _restartRequired = true;
                ReactDialog.CloseCurrentModal();             // close the top Create dialog
                _okButton_Click(null, null);                 // close this dialog
            });

            UpdateDisplay();

            if (CollectionSettingsApi.FixEnterpriseSubscriptionCodeMode)
            {
                _tab.SelectedTab = _enterpriseTab;
            }

            if (tcManager.CurrentCollectionEvenIfDisconnected == null)
            {
                _noRenameTeamCollectionLabel.Visible = false;
            }
            else
            {
                _bloomCollectionName.Enabled = false;
            }
        }
예제 #3
0
        public CollectionSettingsDialog(CollectionSettings collectionSettings, XMatterPackFinder xmatterPackFinder, QueueRenameOfCollection queueRenameOfCollection, PageRefreshEvent pageRefreshEvent, TeamCollectionManager tcManager)
        {
            _collectionSettings      = collectionSettings;
            _xmatterPackFinder       = xmatterPackFinder;
            _queueRenameOfCollection = queueRenameOfCollection;
            _pageRefreshEvent        = pageRefreshEvent;
            InitializeComponent();
            // moved from the Designer where it was deleted if the Designer was touched
            _xmatterList.Columns.AddRange(new[] { new ColumnHeader()
                                                  {
                                                      Width = 250
                                                  } });

            _language1Name.UseMnemonic              = false;    // Allow & to be part of the language display names.
            _language2Name.UseMnemonic              = false;    // This may be unlikely, but can't be ruled out.
            _language3Name.UseMnemonic              = false;    // See https://issues.bloomlibrary.org/youtrack/issue/BL-9919.
            _language1FontLabel.UseMnemonic         = false;
            _language2FontLabel.UseMnemonic         = false;
            _language3FontLabel.UseMnemonic         = false;
            CollectionSettingsApi.DialogBeingEdited = this;

            if (_collectionSettings.IsSourceCollection)
            {
                _language1Label.Text = LocalizationManager.GetString("CollectionSettingsDialog.LanguageTab.Language1InSourceCollection", "Language 1", "In a local language collection, we say 'Local Language', but in a source collection, Local Language has no relevance, so we use this different label");
                _language2Label.Text = LocalizationManager.GetString("CollectionSettingsDialog.LanguageTab.Language2InSourceCollection", "Language 2", "In a local language collection, we say 'Language 2 (e.g. National Language)', but in a source collection, National Language has no relevance, so we use this different label");
                _language3Label.Text = LocalizationManager.GetString("CollectionSettingsDialog.LanguageTab.Language3InSourceCollection", "Language 3", "In a local language collection, we say 'Language 3 (e.g. Regional Language)', but in a source collection, National Language has no relevance, so we use this different label");
            }

            _showExperimentalBookSources.Checked = ExperimentalFeatures.IsFeatureEnabled(ExperimentalFeatures.kExperimentalSourceBooks);
            _allowTeamCollection.Checked         = ExperimentalFeatures.IsFeatureEnabled(ExperimentalFeatures.kTeamCollections);
            if (!ExperimentalFeatures.IsFeatureEnabled(ExperimentalFeatures.kTeamCollections) && tcManager.CurrentCollectionEvenIfDisconnected == null)
            {
                this._tab.Controls.Remove(this._teamCollectionTab);
            }
            // Don't allow the user to disable the Team Collection feature if we're currently in a Team Collection.
            _allowTeamCollection.Enabled = !(_allowTeamCollection.Checked && tcManager.CurrentCollectionEvenIfDisconnected != null);

            // AutoUpdate applies only to Windows: see https://silbloom.myjetbrains.com/youtrack/issue/BL-2317.
            if (SIL.PlatformUtilities.Platform.IsWindows)
            {
                _automaticallyUpdate.Checked = Settings.Default.AutoUpdate;
            }
            else
            {
                _automaticallyUpdate.Hide();
            }

            // Without this, PendingDefaultBookshelf stays null unless the user changes it.
            // The result is the bookshelf selection gets cleared when other collection settings are saved. See BL-10093.
            PendingDefaultBookshelf = _collectionSettings.DefaultBookshelf;

//		    _showSendReceive.CheckStateChanged += (sender, args) =>
//		                                              {
//		                                                  Settings.Default.ShowSendReceive = _showSendReceive.CheckState ==
//		                                                                                     CheckState.Checked;
//
//                                                          _restartRequired = true;
//		                                                  UpdateDisplay();
//		                                              };

            CollectionSettingsApi.BrandingChangeHandler = ChangeBranding;

            SetupEnterpriseBrowser();

            TeamCollectionApi.TheOneInstance.SetCallbackToReopenCollection(() =>
            {
                _restartRequired = true;
                ReactDialog.CloseCurrentModal();             // close the top Create dialog
                _okButton_Click(null, null);                 // close this dialog
            });

            UpdateDisplay();

            if (CollectionSettingsApi.FixEnterpriseSubscriptionCodeMode)
            {
                _tab.SelectedTab = _enterpriseTab;
            }

            if (tcManager.CurrentCollectionEvenIfDisconnected == null)
            {
                _noRenameTeamCollectionLabel.Visible = false;
            }
            else
            {
                _bloomCollectionName.Enabled = false;
            }

            // This code would mostly more naturally go in Designer. Unfortunately we can't run designer
            // until we get back in a state where all our dependencies are sufficiently consistent.

            _defaultBookshelfControl = ReactControl.Create("defaultBookshelfControlBundle");

            tabPage2.Controls.Add(_defaultBookshelfControl);
            _defaultBookshelfControl.Location = new Point(_xmatterDescription.Left, _xmatterDescription.Bottom + 30);
            // We'd like it to be as big as possible, not just big enough for the immediate content.
            // Until React takes over at least the whole tab, the pull-down part of the combo can't
            // stretch outside the Gecko control.
            _defaultBookshelfControl.Size = new Size(_xmatterList.Width, 200);
        }
예제 #4
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);
        }