<commit_before>﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using Bloom.Api;
using Bloom.Book;
using Bloom.Edit;
using Bloom.MiscUI;
using Bloom.TeamCollection;
using Bloom.WebLibraryIntegration;
using Bloom.Workspace;
using L10NSharp;
using Newtonsoft.Json;
using SIL.Extensions;
using SIL.IO;
using SIL.PlatformUtilities;
using ApplicationException = System.ApplicationException;
using Timer = System.Windows.Forms.Timer;

namespace Bloom.web.controllers
{
	/// <summary>
	/// API functions common to various areas of Bloom's HTML UI.
	/// </summary>
	public class CommonApi
	{
		private readonly BookSelection _bookSelection;
		private BloomParseClient _parseClient;
		public static bool AuthorMode { get; set; }
		public EditingModel Model { get; set; }

		// Needed so we can implement CheckForUpdates. Set by the WorkspaceView in its constructor, since
		// Autofac was not able to pass us one.
		public static WorkspaceView WorkspaceView { get; set; }

		// Called by autofac, which creates the one instance and registers it with the server.
		public CommonApi(BookSelection bookSelection, BloomParseClient parseClient)
		{
			_bookSelection = bookSelection;
			_parseClient = parseClient;
		}

		public void RegisterWithApiHandler(BloomApiHandler apiHandler)
		{
			apiHandler.RegisterEndpointHandler("uiLanguages", HandleUiLanguages, false); // App
			apiHandler.RegisterEndpointHandler("currentUiLanguage", HandleCurrentUiLanguage, false); // App
			apiHandler.RegisterEndpointHandler("bubbleLanguages", HandleBubbleLanguages, false); // Move to EditingViewApi
			apiHandler.RegisterEndpointHandler("authorMode", HandleAuthorMode, false); // Move to EditingViewApi
			apiHandler.RegisterEndpointHandler("topics", HandleTopics, false); // Move to EditingViewApi
			apiHandler.RegisterEndpointHandler("common/error", HandleJavascriptError, false); // Common
			apiHandler.RegisterEndpointHandler("common/preliminaryError", HandlePreliminaryJavascriptError, false); // Common
			apiHandler.RegisterEndpointHandler("common/saveChangesAndRethinkPageEvent", RethinkPageAndReloadIt, true); // Move to EditingViewApi
			apiHandler.RegisterEndpointHandler("common/requestTranslationGroups", RequestTranslationGroups, true); // Move to EditingViewApi
			apiHandler.RegisterEndpointHandler("common/showInFolder", HandleShowInFolderRequest, true); // Common
			apiHandler.RegisterEndpointHandler("common/canModifyCurrentBook", HandleCanModifyCurrentBook, true);
			apiHandler.RegisterEndpointHandler("common/showSettingsDialog", HandleShowSettingsDialog, false); // Common
			apiHandler.RegisterEndpointHandler("common/problemWithBookMessage", request =>
			{
				request.ReplyWithText(CommonMessages.GetProblemWithBookMessage(Path.GetFileName(_bookSelection.CurrentSelection?.FolderPath)));
			}, false);
			apiHandler.RegisterEndpointHandler("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.
			apiHandler.RegisterEndpointHandler("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 = Clipboard.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
								{
									Clipboard.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);
			apiHandler.RegisterEndpointHandler("common/checkForUpdates",
				request =>
				{
					WorkspaceView.CheckForUpdates();
					request.PostSucceeded();
				}, false);
			apiHandler.RegisterEndpointHandler("common/channel",
				request =>
				{
					request.ReplyWithText(ApplicationUpdateSupport.ChannelName);
				}, false);<commit_msg>Replace Clipboard with PortableClipboard in Version5.0 (BL-10469)<commit_after>﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using Bloom.Api;
using Bloom.Book;
using Bloom.Edit;
using Bloom.MiscUI;
using Bloom.TeamCollection;
using Bloom.WebLibraryIntegration;
using Bloom.Workspace;
using L10NSharp;
using Newtonsoft.Json;
using SIL.Extensions;
using SIL.IO;
using SIL.PlatformUtilities;
using SIL.Windows.Forms.Miscellaneous;
using ApplicationException = System.ApplicationException;
using Timer = System.Windows.Forms.Timer;

namespace Bloom.web.controllers
{
	/// <summary>
	/// API functions common to various areas of Bloom's HTML UI.
	/// </summary>
	public class CommonApi
	{
		private readonly BookSelection _bookSelection;
		private BloomParseClient _parseClient;
		public static bool AuthorMode { get; set; }
		public EditingModel Model { get; set; }

		// Needed so we can implement CheckForUpdates. Set by the WorkspaceView in its constructor, since
		// Autofac was not able to pass us one.
		public static WorkspaceView WorkspaceView { get; set; }

		// Called by autofac, which creates the one instance and registers it with the server.
		public CommonApi(BookSelection bookSelection, BloomParseClient parseClient)
		{
			_bookSelection = bookSelection;
			_parseClient = parseClient;
		}

		public void RegisterWithApiHandler(BloomApiHandler apiHandler)
		{
			apiHandler.RegisterEndpointHandler("uiLanguages", HandleUiLanguages, false); // App
			apiHandler.RegisterEndpointHandler("currentUiLanguage", HandleCurrentUiLanguage, false); // App
			apiHandler.RegisterEndpointHandler("bubbleLanguages", HandleBubbleLanguages, false); // Move to EditingViewApi
			apiHandler.RegisterEndpointHandler("authorMode", HandleAuthorMode, false); // Move to EditingViewApi
			apiHandler.RegisterEndpointHandler("topics", HandleTopics, false); // Move to EditingViewApi
			apiHandler.RegisterEndpointHandler("common/error", HandleJavascriptError, false); // Common
			apiHandler.RegisterEndpointHandler("common/preliminaryError", HandlePreliminaryJavascriptError, false); // Common
			apiHandler.RegisterEndpointHandler("common/saveChangesAndRethinkPageEvent", RethinkPageAndReloadIt, true); // Move to EditingViewApi
			apiHandler.RegisterEndpointHandler("common/requestTranslationGroups", RequestTranslationGroups, true); // Move to EditingViewApi
			apiHandler.RegisterEndpointHandler("common/showInFolder", HandleShowInFolderRequest, true); // Common
			apiHandler.RegisterEndpointHandler("common/canModifyCurrentBook", HandleCanModifyCurrentBook, true);
			apiHandler.RegisterEndpointHandler("common/showSettingsDialog", HandleShowSettingsDialog, false); // Common
			apiHandler.RegisterEndpointHandler("common/problemWithBookMessage", request =>
			{
				request.ReplyWithText(CommonMessages.GetProblemWithBookMessage(Path.GetFileName(_bookSelection.CurrentSelection?.FolderPath)));
			}, false);
			apiHandler.RegisterEndpointHandler("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.
			apiHandler.RegisterEndpointHandler("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);
			apiHandler.RegisterEndpointHandler("common/checkForUpdates",
				request =>
				{
					WorkspaceView.CheckForUpdates();
					request.PostSucceeded();
				}, false);
			apiHandler.RegisterEndpointHandler("common/channel",
				request =>
				{
					request.ReplyWithText(ApplicationUpdateSupport.ChannelName);
				}, false);
{'fraction_non_alphanumeric': 0.09091766481184571, 'fraction_numerical': 0.0010374422333301896, 'mean_word_length': 3.9183673469387754, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5819228', 'n_tokens_mistral': 3530, 'n_tokens_neox': 2760, 'n_words': 731}