diff --git a/.gitattributes b/.gitattributes index f8d3ba2886..01fa7c94ef 100644 --- a/.gitattributes +++ b/.gitattributes @@ -11,3 +11,4 @@ *.woff binary *.woff2 binary *.ldml binary +*.zip binary diff --git a/assets/localization/en.json b/assets/localization/en.json index 4517499d4d..e59a8415c1 100644 --- a/assets/localization/en.json +++ b/assets/localization/en.json @@ -1,6 +1,9 @@ { "%about_versionLabel_format%": "Version: {version}", "%about_licenseLabel_format%": "License: {license}", + "%about_db_ip_attribution_format%": "{intro} {websiteLink} ({license}, {terms})", + "%about_db_ip_attribution_intro%": "Internet safety features use data from", + "%about_db_ip_attribution_terms%": "Terms", "%downloadResources_errorRegistrationInvalid%": "User registration is not valid. Cannot retrieve resources from DBL.", "%downloadResources_errorInstallResource_resourceNotFound%": "Resource not available from DBL", "%downloadResources_errorInstallResource_resourceAlreadyInstalled%": "Resource is already installed and up to date. Installation skipped.", diff --git a/assets/localization/es.json b/assets/localization/es.json index 12f9f22a06..4c4180c6cd 100644 --- a/assets/localization/es.json +++ b/assets/localization/es.json @@ -1,9 +1,142 @@ { "%about_versionLabel_format%": "Versión: {version}", "%about_licenseLabel_format%": "Licencia: {license}", + "%Book.GEN%": "Génesis", + "%Book.LEV%": "Levítico", + "%Book.NUM%": "Números", + "%Book.DEU%": "Deuteronomio", + "%Book.JOS%": "Josué", + "%Book.JDG%": "Jueces", + "%Book.RUT%": "Rut", + "%Book.1SA%": "1 Samuel", + "%Book.2SA%": "2 Samuel", + "%Book.1KI%": "1 Reyes", + "%Book.2KI%": "2 Reyes", + "%Book.1CH%": "1 Crónicas", + "%Book.2CH%": "2 Crónicas", + "%Book.EZR%": "Esdras", + "%Book.NEH%": "Nehemías", + "%Book.EST%": "Ester (hebreo)", + "%Book.JOB%": "Job", + "%Book.PSA%": "Salmos", + "%Book.PRO%": "Proverbios", + "%Book.ECC%": "Eclesiastés", + "%Book.SNG%": "Cantar de los cantares", + "%Book.ISA%": "Isaías", + "%Book.JER%": "Jeremías", + "%Book.LAM%": "Lamentaciones", + "%Book.EZK%": "Ezequiel", + "%Book.DAN%": "Daniel (hebreo)", + "%Book.HOS%": "Oseas", + "%Book.JOL%": "Joel", + "%Book.AMO%": "Amós", + "%Book.OBA%": "Abdías", + "%Book.JON%": "Jonás", + "%Book.MIC%": "Miqueas", + "%Book.NAM%": "Nahúm", + "%Book.HAB%": "Habacuc", + "%Book.ZEP%": "Sofonías", + "%Book.HAG%": "Hageo", + "%Book.ZEC%": "Zacarías", + "%Book.MAL%": "Malaquías", + "%Book.MAT%": "Mateo", + "%Book.MRK%": "Marcos", + "%Book.LUK%": "Lucas", + "%Book.JHN%": "Juan", + "%Book.ACT%": "Hechos", + "%Book.ROM%": "Romanos", + "%Book.1CO%": "1 Corintios", + "%Book.2CO%": "2 Corintios", + "%Book.GAL%": "Gálatas", + "%Book.EPH%": "Efesios", + "%Book.PHP%": "Filipenses", + "%Book.COL%": "Colosenses", + "%Book.1TH%": "1 Tesalonicenses", + "%Book.2TH%": "2 Tesalonicenses", + "%Book.1TI%": "1 Timoteo", + "%Book.2TI%": "2 Timoteo", + "%Book.TIT%": "Tito", + "%Book.PHM%": "Filemón", + "%Book.HEB%": "Hebreos", + "%Book.JAS%": "Santiago", + "%Book.1PE%": "1 Pedro", + "%Book.2PE%": "2 Pedro", + "%Book.1JN%": "1 Juan", + "%Book.2JN%": "2 Juan", + "%Book.3JN%": "3 Juan", + "%Book.JUD%": "Judas", + "%Book.REV%": "Apocalipsis", + "%Book.TOB%": "Tobías", + "%Book.JDT%": "Judit", + "%Book.ESG%": "Ester (griego)", + "%Book.WIS%": "Sabiduría", + "%Book.SIR%": "Sirach (Eclesiástico)", + "%Book.BAR%": "Baruc", + "%Book.LJE%": "Carta de Jeremías", + "%Book.S3Y%": "Canto de los tres jóvenes", + "%Book.SUS%": "Susana", + "%Book.BEL%": "Bel y la Serpiente", + "%Book.1MA%": "1 Macabeos", + "%Book.2MA%": "2 Macabeos", + "%Book.3MA%": "3 Macabeos", + "%Book.4MA%": "4 Macabeos", + "%Book.1ES%": "1 Esdras (griego)", + "%Book.2ES%": "2 Esdras (Latin)", + "%Book.MAN%": "Oración de Manasés", + "%Book.PS2%": "Salmos de Salomón", + "%Book.ODA%": "Odas", + "%Book.PSS%": "Salmos de Salomón", + "%Book.JSA%": "Josué A. *obsoleto*", + "%Book.JDB%": "Jueces B. *obsoleto*", + "%Book.TBS%": "Tobías S. *obsoleto*", + "%Book.SST%": "Susana Th. *obsoleto*", + "%Book.DNT%": "Daniel Th. *obsoleto*", + "%Book.BLT%": "Bel Th. *obsoleto*", + "%Book.XXA%": "Extra A", + "%Book.XXB%": "Extra B", + "%Book.XXC%": "Extra C", + "%Book.XXD%": "Extra D", + "%Book.XXE%": "Extra E", + "%Book.XXF%": "Extra F", + "%Book.XXG%": "Extra G", + "%Book.FRT%": "Páginas iniciales", + "%Book.BAK%": "Páginas finales", + "%Book.OTH%": "Otra materia", + "%Book.3ES%": "3 Esdras *obsoleto*", + "%Book.EZA%": "Apocalipsis de Esdras", + "%Book.5EZ%": "5 Esdras (Prólogo en Latín)", + "%Book.6EZ%": "6 Esdras (Prólogo en Latín)", + "%Book.INT%": "Introducción", + "%Book.CNC%": "Concordancia ", + "%Book.GLO%": "Glosario ", + "%Book.TDX%": "Índice de temas", + "%Book.NDX%": "Índice de nombres", + "%Book.DAG%": "Daniel griego", + "%Book.PS3%": "Salmos 152-155", + "%Book.2BA%": "2 Baruc (Apocalipsis)", + "%Book.LBA%": "Carta de Baruch", + "%Book.JUB%": "Jubileos", + "%Book.ENO%": "Enoc", + "%Book.1MQ%": "1 Macabeos (Etiópe)", + "%Book.2MQ%": "2 Macabeos (Etiópe)", + "%Book.3MQ%": "3 Macabeos (Etiópe)", + "%Book.REP%": "Re-examinar (Proverbios 25-31)", + "%Book.4BA%": "4 Baruc (El resto de Baruc)", + "%Book.LAO%": "Laodicenos", + "%downloadUpdateProjectTab_aria_downloadable%": "proyectos descargables", + "%downloadUpdateProjectTab_aria_downloaded%": "proyectos descargables", + "%downloadUpdateProjectTab_button_delete%": "Eliminar", + "%downloadUpdateProjectTab_listHeader_downloadable%": "Proyectos Descargables", + "%downloadUpdateProjectTab_listHeader_downloaded%": "Proyectos Descargables", + "%downloadUpdateProjectTab_title_downloadUpdate%": "Descargar/Actualizar Proyecto", + "%general_button_submit%": "Enviar", + "%general_cancel%": "Cancelar", + "%general_error_title%": "Error", + "%general_loading%": "Cargando", + "%general_run%": "Ejecutar", "%insertNote%": "Insertar Nota", "%mainMenu_about%": "Acerca de Platform.Bible", - "%mainMenu_downloadSlashInstallResources%": "Descargar/instalar recursos", + "%mainMenu_downloadInstallResources%": "Descargar/instalar recursos", "%mainMenu_downloadSlashUpdateProject%": "Descargar/actualizar proyecto", "%mainMenu_exit%": "Salir", "%mainMenu_help%": "Ayuda", @@ -13,15 +146,53 @@ "%mainMenu_settings%": "Configuración", "%mainMenu_visitSupportBible%": "Visitar Support.Bible", "%mainMenu_window%": "Ventana", + "%menuItemName_wordList%": "Lista de Palabras", + "%product_name%": "Plataforma.Biblia", + "%project_full_name_missing%": "*Falta el Nombre*", + "%project_language_missing%": "*Falta el Idioma*", + "%project_name_missing%": "_SinNombre_", + "%project_settings_platform_fullName_label%": "Nombre Completo del Proyecto", + "%project_settings_platform_group1_description%": "Configuración del proyecto relacionada con el software en general", + "%project_settings_platform_group1_label%": "Configuración de la Plataforma", + "%project_settings_platform_isEditable_label%": "Es Editable", + "%project_settings_platform_isEditable_description%": "Si este proyecto es editable. Un proyecto que no es editable a veces se denomina recurso.", + "%project_settings_platform_language_label%": "Lenguaje Primario del Proyecto", + "%project_settings_platform_name_label%": "Nombre Abreviado del Proyecto", + "%scrollGroup_0%": "A", + "%scrollGroup_1%": "B", + "%scrollGroup_2%": "C", + "%scrollGroup_3%": "D", + "%scrollGroup_4%": "E", + "%scrollGroup_undefined%": "Ø", + "%selectBooks_title_selectBooks%": "Seleccionar libros", + "%selectMultipleProjects_title_selectProjects%": "Seleccionar Proyectos", + "%selectProject_title%": "Seleccionar Proyecto", + "%settings_platform_comments_enabled_description%": "Habilitado la lectura y escritura de comentarios en proyectos. Esta es una característica experimental.", + "%settings_platform_comments_enabled_label%": "Comentarios habilitados (experimental)", + "%settings_defaultMessage_loadingSetting%": "Cargando configuración", + "%settings_defaultSearchText_searchProject%": "Buscar Configuración del Proyecto...", + "%settings_defaultSearchText_searchUserSettings%": "Buscar Configuración del Usuario...", + "%settings_platform_group1_description%": "Configuraciones generales del software fundamental", + "%settings_platform_group1_label%": "Configuración de la Plataforma", + "%settings_platform_interfaceLanguage_description%": "Lista de locales usados al localizar la interfaz en orden descendente de prioridad. 'en' (inglés) siempre se añade al final, de modo que si no se encuentra una traducción en ninguno de los idiomas especificados, aparecerá en inglés.", + "%settings_platform_label_group1%": "Configuraciones de Platform", + "%settings_platform_interfaceLanguage_label%": "Idioma de interfaz", + "%settings_platform_paratextDataLastRegistryDataCachedTimes_label%": "ParatextData Últimos Datos del Registro Almacenados en Caché", + "%settings_platform_ptxUtilsMementoData_label%": "Datos de Recuerdo de PtxUtils", + "%settings_platform_verseRef_description%": "Referencia de Verso Actual para el Grupo de Desplazamiento A. Obsoleto - Por favor use `papi.scrollGroups` y `useWebViewScrollGroupScrRef`", + "%settings_platform_verseRef_label%": "Referencia de Verso Actual para el Grupo de Desplazamiento A (Obsoleto)", + "%settings_title_projectSettings%": "Configuración del Proyecto", + "%settings_title_userSettings%": "Configuración del Usuario", "%some_localization_key%": "Esto es el texto en español para %some_localization_key%.", "%submitButton%": "Enviar", + "%tab_aria_tab%": "Pestaña", + "%tab_title_error%": "Error", + "%tab_title_unknown%": "Desconocido", + "%webView_defaultTitle_webView%": "Vista Web", "%webView_edit%": "Editar", "%webView_openProjectSettings%": "Abrir configuraciones del proyecto", "%webView_project%": "Proyecto", "%webView_projectAssignmentsAndProgress%": "Asignaciones y progreso", - "%wordList%": "Lista de palabras", - "%settings_platform_group1_description%": "Configuraciones generales del software fundamental", - "%settings_platform_interfaceLanguage_description%": "Lista de locales usados al localizar la interfaz en orden descendente de prioridad. 'en' (inglés) siempre se añade al final, de modo que si no se encuentra una traducción en ninguno de los idiomas especificados, aparecerá en inglés.", - "%settings_platform_label_group1%": "Configuraciones de Platform", - "%settings_platform_interfaceLanguage_label%": "Idioma de interfaz" + "%webView_title_type_formatString%": "{type} {defaultTitle}", + "%wordList%": "Lista de palabras" } diff --git a/assets/localization/metadata.json b/assets/localization/metadata.json index e88230030c..38947b81c9 100644 --- a/assets/localization/metadata.json +++ b/assets/localization/metadata.json @@ -5,5 +5,11 @@ }, "%submit%": { "fallbackKey": "%yes%" + }, + "%about_db_ip_attribution_intro%": { + "fallbackKey": "%Paratext.Base.SplashScreen.Splash_Load." Internet safety features use data from "%" + }, + "%about_db_ip_attribution_terms%": { + "fallbackKey": "%Paratext.Base.SplashScreen.Splash_Load."Terms"%" } } diff --git a/c-sharp/JsonUtils/InternetSettingsMementoConverter.cs b/c-sharp/JsonUtils/InternetSettingsMementoConverter.cs new file mode 100644 index 0000000000..aa9299ff3e --- /dev/null +++ b/c-sharp/JsonUtils/InternetSettingsMementoConverter.cs @@ -0,0 +1,193 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using Paratext.Data; + +namespace Paranext.DataProvider.JsonUtils; + +public class InternetSettingsMementoConverter + : JsonConverter +{ + private const string SELECTED_SERVER = "selectedServer"; + private const string PERMITTED_INTERNET_USE = "permittedInternetUse"; + private const string PROXY_PORT = "proxyPort"; + private const string PROXY_HOST = "proxyHost"; + private const string PROXY_USERNAME = "proxyUsername"; + private const string PROXY_PASSWORD = "proxyPassword"; + private const string PROXY_MODE = "proxyMode"; + private const string OVERRIDE_DBL_SERVER = "overrideDBLServer"; + private const string OVERRIDE_DBL_API_SERVER = "overrideDBLApiServer"; + private const string OVERRIDE_GBC_SERVER = "overrideGbcServer"; + private const string DBL_EMAIL = "dblEmail"; + private const string DBL_PASSWORD = "dblPassword"; + + public override InternetAccess.InternetSettingsMemento Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + ServerType selectedServer = ServerType.Production; + InternetUse permittedInternetUse = InternetUse.VpnRequired; + int proxyPort = 0; + string? proxyHost = null; + string? proxyUsername = null; + string? proxyPassword = null; + string? proxyMode = null; + string? overrideDBLServer = null; + string? overrideDBLApiServer = null; + string? overrideGbcServer = null; + string? dblEmail = null; + string? dblPassword = null; + + string? lastPropertyName = null; + // The starting token is consumed before we get the reader + int onObjectLevel = 1; + while (onObjectLevel > 0 && reader.Read()) + { + switch (reader.TokenType) + { + case JsonTokenType.StartObject: + case JsonTokenType.StartArray: + onObjectLevel++; + break; + case JsonTokenType.EndObject: + case JsonTokenType.EndArray: + onObjectLevel--; + break; + case JsonTokenType.PropertyName: + lastPropertyName = reader.GetString(); + break; + case JsonTokenType.True: + case JsonTokenType.False: + lastPropertyName = null; + break; + case JsonTokenType.Number: + switch (lastPropertyName) + { + case PROXY_PORT: + proxyPort = reader.GetInt32(); + break; + } + lastPropertyName = null; + break; + case JsonTokenType.String: + switch (lastPropertyName) + { + case SELECTED_SERVER: + var selectedServerString = reader.GetString(); + if (!string.IsNullOrEmpty(selectedServerString)) + { + selectedServer = selectedServerString switch + { + "Production" => ServerType.Production, + "QualityAssurance" => ServerType.QualityAssurance, + "Development" => ServerType.Development, + "Test" => ServerType.Test, + _ => throw new JsonException( + $"Invalid selectedServer value {selectedServerString}! Must provide a ServerType value" + ), + }; + } + break; + case PERMITTED_INTERNET_USE: + var permittedInternetUseString = reader.GetString(); + if (!string.IsNullOrEmpty(permittedInternetUseString)) + { + permittedInternetUse = permittedInternetUseString switch + { + "Enabled" => InternetUse.Enabled, + "VpnRequired" => InternetUse.VpnRequired, + "Disabled" => InternetUse.Disabled, + "ProxyOnly" => InternetUse.ProxyOnly, + _ => throw new JsonException( + $"Invalid permittedInternetUse value {permittedInternetUseString}! Must provide an InternetUse value" + ), + }; + } + break; + case PROXY_HOST: + proxyHost = reader.GetString() ?? ""; + break; + case PROXY_USERNAME: + proxyUsername = reader.GetString() ?? ""; + break; + case PROXY_PASSWORD: + proxyPassword = reader.GetString() ?? ""; + break; + case PROXY_MODE: + proxyMode = reader.GetString() ?? ""; + break; + case OVERRIDE_DBL_SERVER: + overrideDBLServer = reader.GetString() ?? ""; + break; + case OVERRIDE_DBL_API_SERVER: + overrideDBLApiServer = reader.GetString() ?? ""; + break; + case OVERRIDE_GBC_SERVER: + overrideGbcServer = reader.GetString() ?? ""; + break; + case DBL_EMAIL: + dblEmail = reader.GetString() ?? ""; + break; + case DBL_PASSWORD: + dblPassword = reader.GetString() ?? ""; + break; + } + lastPropertyName = null; + break; + } + } + + return new InternetAccess.InternetSettingsMemento + { + SelectedServer = selectedServer, + PermittedInternetUse = permittedInternetUse, + ProxyPort = proxyPort, + ProxyHost = proxyHost, + ProxyUsername = proxyUsername, + ProxyPassword = proxyPassword, + ProxyMode = proxyMode, + OverrideDBLServer = overrideDBLServer, + OverrideDBLApiServer = overrideDBLApiServer, + OverrideGbcServer = overrideGbcServer, + DBLEmail = dblEmail, + DBLPassword = dblPassword, + }; + } + + public override void Write( + Utf8JsonWriter writer, + InternetAccess.InternetSettingsMemento value, + JsonSerializerOptions options + ) + { + writer.WriteStartObject(); + var selectedServer = value.SelectedServer switch + { + ServerType.QualityAssurance => "QualityAssurance", + ServerType.Development => "Development", + ServerType.Test => "Test", + _ => "Production", + }; + writer.WriteString(SELECTED_SERVER, selectedServer); + var permittedInternetUse = value.PermittedInternetUse switch + { + InternetUse.Enabled => "Enabled", + InternetUse.Disabled => "Disabled", + InternetUse.ProxyOnly => "ProxyOnly", + _ => "VpnRequired", + }; + writer.WriteString(PERMITTED_INTERNET_USE, permittedInternetUse); + writer.WriteNumber(PROXY_PORT, value.ProxyPort); + writer.WriteString(PROXY_HOST, value.ProxyHost); + writer.WriteString(PROXY_USERNAME, value.ProxyUsername); + writer.WriteString(PROXY_PASSWORD, value.ProxyPassword); + writer.WriteString(PROXY_MODE, value.ProxyMode); + writer.WriteString(OVERRIDE_DBL_SERVER, value.OverrideDBLServer); + writer.WriteString(OVERRIDE_DBL_API_SERVER, value.OverrideDBLApiServer); + writer.WriteString(OVERRIDE_GBC_SERVER, value.OverrideGbcServer); + writer.WriteString(DBL_EMAIL, value.DBLEmail); + writer.WriteString(DBL_PASSWORD, value.DBLPassword); + writer.WriteEndObject(); + } +} diff --git a/c-sharp/JsonUtils/SerializationOptions.cs b/c-sharp/JsonUtils/SerializationOptions.cs index 061baa2ee3..c968d37b4a 100644 --- a/c-sharp/JsonUtils/SerializationOptions.cs +++ b/c-sharp/JsonUtils/SerializationOptions.cs @@ -25,6 +25,7 @@ public static JsonSerializerOptions CreateSerializationOptions() options.Converters.Add(new CommentConverter()); options.Converters.Add(new VerseRefConverter()); options.Converters.Add(new RegistrationDataConverter()); + options.Converters.Add(new InternetSettingsMementoConverter()); return options; } diff --git a/c-sharp/ParanextDataProvider.csproj b/c-sharp/ParanextDataProvider.csproj index b18087bf86..222e08e9a6 100644 --- a/c-sharp/ParanextDataProvider.csproj +++ b/c-sharp/ParanextDataProvider.csproj @@ -70,6 +70,19 @@ Always + + + PreserveNewest + %(Filename)%(Extension) + diff --git a/c-sharp/Projects/LocalParatextProjects.cs b/c-sharp/Projects/LocalParatextProjects.cs index a1e326999f..ab41adbcc3 100644 --- a/c-sharp/Projects/LocalParatextProjects.cs +++ b/c-sharp/Projects/LocalParatextProjects.cs @@ -24,7 +24,12 @@ internal class LocalParatextProjects private bool _isInitialized = false; private readonly object _initializationLock = new(); - private readonly List _requiredProjectRootFiles = ["usfm.sty", "Attribution.md"]; + private readonly List _requiredProjectRootFiles = + [ + "usfm.sty", + "Attribution.md", + "CountryStatuses.xml", + ]; private static readonly List s_paratextProjectInterfaces = [ diff --git a/c-sharp/Users/ParatextRegistrationService.cs b/c-sharp/Users/ParatextRegistrationService.cs index 9b7fa0bb28..40e8792111 100644 --- a/c-sharp/Users/ParatextRegistrationService.cs +++ b/c-sharp/Users/ParatextRegistrationService.cs @@ -1,6 +1,5 @@ using Paranext.DataProvider.Services; using Paratext.Data; -using Paratext.Data.RegistryServerAccess; using Paratext.Data.Repository; using Paratext.Data.Users; using PtxUtils; @@ -14,18 +13,17 @@ internal class ParatextRegistrationService(PapiClient papiClient) { #region Constructors, consts, and fields - /// - /// Time in milliseconds to wait before restarting the application after changing Paratext - /// registration information - /// - private const int REGISTRATION_CHANGE_RESTART_DELAY_MS = 5 * 1000; - /// /// Placeholder to show instead of real registration code so we aren't giving out the real /// registration code /// private const string PLACEHOLDER_CODE = "******-******-******-******-******"; + /// + /// Placeholder to show instead of real passwords so we aren't giving out real passwords + /// + private const string PLACEHOLDER_PASSWORD = "********"; + #endregion #region Public properties and methods @@ -45,6 +43,14 @@ await PapiClient.RegisterRequestHandlerAsync( "command:paratextRegistration.doesUserHaveValidRegistration", () => RegistrationInfo.DefaultUser.IsValid ); + await PapiClient.RegisterRequestHandlerAsync( + "command:paratextRegistration.getParatextDataInternetSettings", + GetParatextDataInternetSettings + ); + await PapiClient.RegisterRequestHandlerAsync( + "command:paratextRegistration.setParatextDataInternetSettings", + SetParatextDataInternetSettings + ); // Lookup localized strings where they may be needed by callers without access to PapiClient RegistrationRequiredException.ExceptionMessage = LocalizationService.GetLocalizedString( @@ -63,7 +69,6 @@ await PapiClient.RegisterRequestHandlerAsync( /// /// Returns information about user's current Paratext Registry user information in ParatextData.dll /// - /// Contents of command request. No contents expected /// Paratext registration information private RegistrationData GetParatextRegistrationData() { @@ -93,10 +98,8 @@ private RegistrationData GetParatextRegistrationData() /// /// Sets information about user's current Paratext Registry user information in ParatextData.dll - /// and restarts the application /// - /// Contents of command request. Array whose first entry is the registration data object - /// `true` if successfully updated; `false` otherwise + /// registration data object for updating registration private void SetParatextRegistrationData(RegistrationData newRegistrationData) { bool shouldSkipAppendingToExceptionMessage = false; @@ -182,17 +185,8 @@ private void SetParatextRegistrationData(RegistrationData newRegistrationData) RegistrationInfo.ChangeRegistrationData(newRegistrationData); // registration code may have changed, so reset the registry server with the new user data - RegistryServer.Default?.ResetServer(RegistrationInfo.DefaultUser); - - // Restart the application after a delay. Don't wait for it so the response goes through - ThreadingUtils.RunTask( - Task.Delay(REGISTRATION_CHANGE_RESTART_DELAY_MS) - .ContinueWith( - async (Task task) => - await PapiClient.SendRequestAsync("command:platform.restart", []), - TaskScheduler.Default - ), - "ParatextRegistrationService sending request to restart the application" + Paratext.Data.RegistryServerAccess.RegistryServer.Default?.ResetServer( + RegistrationInfo.DefaultUser ); } catch (Exception e) @@ -206,6 +200,106 @@ await PapiClient.SendRequestAsync("command:platform.restart", []), } } + /// + /// Returns information about user's current ParatextData.dll internet settings + /// + /// Contents of command request. No contents expected + /// Paratext registration information + private InternetAccess.InternetSettingsMemento GetParatextDataInternetSettings() + { + try + { + var internetSettings = new InternetAccess.InternetSettingsMemento + { + SelectedServer = InternetAccess.SelectedServers, + PermittedInternetUse = InternetAccess.RawStatus, + ProxyHost = InternetAccess.ProxyHost, + ProxyPort = InternetAccess.ProxyPort, + ProxyUsername = InternetAccess.ProxyUsername, + ProxyPassword = !string.IsNullOrEmpty(InternetAccess.ProxyPassword) + ? PLACEHOLDER_PASSWORD + : null, + ProxyMode = InternetAccess.ProxyMode, + OverrideDBLServer = InternetAccess.OverrideDBLServer, + OverrideDBLApiServer = InternetAccess.OverrideDBLApiServer, + OverrideGbcServer = InternetAccess.OverrideGbcServer, + DBLEmail = InternetAccess.DBLEmail, + DBLPassword = !string.IsNullOrEmpty(InternetAccess.DBLPassword) + ? PLACEHOLDER_PASSWORD + : null, + }; + return internetSettings; + } + catch (Exception e) + { + Console.WriteLine($"Getting ParatextData InternetSettings failed! {e}"); + throw new Exception($"Getting ParatextData InternetSettings failed! {e.Message}"); + } + } + + /// + /// Sets information about user's current ParatextData.dll internet settings + /// + /// internet settings object for updating ParatextData.dll internet settings + private void SetParatextDataInternetSettings( + InternetAccess.InternetSettingsMemento newInternetSettings + ) + { + try + { + // Set empty strings to null (except proxy-related settings since they are handled by + // SetProxy) so they are removed from `InternetSettings.xml` as it happens in PT9 + if (newInternetSettings.OverrideDBLServer == "") + newInternetSettings.OverrideDBLServer = null; + if (newInternetSettings.OverrideDBLApiServer == "") + newInternetSettings.OverrideDBLApiServer = null; + if (newInternetSettings.OverrideGbcServer == "") + newInternetSettings.OverrideGbcServer = null; + if (newInternetSettings.DBLEmail == "") + newInternetSettings.DBLEmail = null; + if (newInternetSettings.DBLPassword == "") + newInternetSettings.DBLPassword = null; + + // Unfortunately, `InternetAccess.SetProxy` is the only way to set proxy properties, and + // it does some weird stuff. Make sure `ProxyHost` is `null` if not using a proxy. Then + // `InternetAccess.SetProxy` will set the proxy properties to `null`. But it will also + // set `RawStatus` to `InternetUse.Disabled`, so set that back to whatever the user + // selected if they selected something that is not `InternetUse.ProxyOnly`. But we want + // to leave it disabled if they selected `InternetUse.ProxyOnly` but provided no host + if (newInternetSettings.PermittedInternetUse != InternetUse.ProxyOnly) + newInternetSettings.ProxyHost = null; + InternetAccess.SetProxy( + newInternetSettings.ProxyHost, + newInternetSettings.ProxyPort, + newInternetSettings.ProxyUsername, + newInternetSettings.ProxyPassword != PLACEHOLDER_PASSWORD + ? newInternetSettings.ProxyPassword + : InternetAccess.ProxyPassword, + newInternetSettings.ProxyMode + ); + if ( + InternetAccess.RawStatus == InternetUse.Disabled + && newInternetSettings.PermittedInternetUse != InternetUse.Disabled + && newInternetSettings.PermittedInternetUse != InternetUse.ProxyOnly + ) + InternetAccess.RawStatus = newInternetSettings.PermittedInternetUse; + + InternetAccess.SelectedServers = newInternetSettings.SelectedServer; + + InternetAccess.OverrideDBLServer = newInternetSettings.OverrideDBLServer; + InternetAccess.OverrideDBLApiServer = newInternetSettings.OverrideDBLApiServer; + InternetAccess.OverrideGbcServer = newInternetSettings.OverrideGbcServer; + InternetAccess.DBLEmail = newInternetSettings.DBLEmail; + if (newInternetSettings.DBLPassword != PLACEHOLDER_PASSWORD) + InternetAccess.DBLPassword = newInternetSettings.DBLPassword; + } + catch (Exception e) + { + Console.WriteLine($"Setting ParatextData InternetSettings failed! {e}"); + throw new Exception($"Setting Paratext Registration data failed! {e.Message}"); + } + } + /// /// For any project with uncommitted changes on this machine, marks a point in project history in /// preparation for switching to a different Paratext user. diff --git a/c-sharp/assets/CountryStatuses.xml b/c-sharp/assets/CountryStatuses.xml new file mode 100644 index 0000000000..a860fe6aef --- /dev/null +++ b/c-sharp/assets/CountryStatuses.xml @@ -0,0 +1,253 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/c-sharp/base-directory-assets/IP-Country.zip b/c-sharp/base-directory-assets/IP-Country.zip new file mode 100644 index 0000000000..e415eecde8 Binary files /dev/null and b/c-sharp/base-directory-assets/IP-Country.zip differ diff --git a/extensions/.stylelintrc.cjs b/extensions/.stylelintrc.cjs index a8534cc879..f959736685 100644 --- a/extensions/.stylelintrc.cjs +++ b/extensions/.stylelintrc.cjs @@ -13,6 +13,10 @@ module.exports = { }, ], rules: { + // Disable Stylelint's indentation control + '@stylistic/indentation': null, + // Let Prettier handle selector list formatting + '@stylistic/selector-list-comma-newline-after': null, 'color-named': null, 'max-nesting-depth': 2, 'no-descending-specificity': null, diff --git a/extensions/package.json b/extensions/package.json index 5d5cf51a42..751b543d61 100644 --- a/extensions/package.json +++ b/extensions/package.json @@ -11,6 +11,8 @@ "watch": "npm run build -- --watch", "build:production": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=false webpack", "watch:production": "npm run build:production -- --watch", + "format": "prettier --write .", + "format:check": "prettier --check .", "zip": "tsx ./lib/zip-extensions.ts", "package": "npm run build:production && npm run zip", "package:debug": "cross-env DEBUG_PROD=true npm run package", @@ -21,7 +23,7 @@ "lint:scripts": "cross-env NODE_OPTIONS=\"--max-old-space-size=4096\" NODE_ENV=development eslint --ext .cjs,.js,.jsx,.ts,.tsx --cache .", "lint:styles": "stylelint **/*.{css,scss}", "lint-fix": "npm run lint-fix:scripts && npm run lint:styles -- --fix", - "lint-fix:scripts": "prettier --write \"**/*.{ts,tsx,js,jsx,cjs}\" && npm run lint:scripts", + "lint-fix:scripts": "npm run format && npm run lint:scripts", "lint:staged": "lint-staged -q", "postinstall": "tsx ./lib/add-remotes.ts", "create-extension": "tsx ./lib/create-extension.ts", diff --git a/extensions/src/evil/assets/evil.web-view.html b/extensions/src/evil/assets/evil.web-view.html index c8d010dfd2..990166a95e 100644 --- a/extensions/src/evil/assets/evil.web-view.html +++ b/extensions/src/evil/assets/evil.web-view.html @@ -1,4 +1,4 @@ - +