Skip to content

Commit

Permalink
Made extension contributions load in order, added spinner, updated Pa…
Browse files Browse the repository at this point in the history
…ratextData to 9.5.0.6, misc bug fixes and improvements (#1066)
  • Loading branch information
tjcouch-sil authored Aug 15, 2024
2 parents fcaa770 + 3c1d8b9 commit c9a163c
Show file tree
Hide file tree
Showing 51 changed files with 2,377 additions and 1,752 deletions.
3 changes: 2 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
"processName": "ParanextDataProvider",
"windows": {
"processName": "ParanextDataProvider.exe"
}
},
"justMyCode": false
},
{
"name": "Debug Platform Backend",
Expand Down
3 changes: 2 additions & 1 deletion assets/localization/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@
"%webView_edit%": "Edit",
"%webView_project%": "Project",
"%webView_projectAssignmentsAndProgress%": "Assignments and Progress",
"%webView_projectSendReceive%": "Send/Receive this project",
"%wordList%": "Word List",
"%settings_platform_group1_label%": "Platform Settings",
"%settings_platform_group1_description%": "Settings pertaining to the software overall",
"%settings_platform_verseRef_label%": "Current Verse Reference",
"%settings_platform_interfaceLanguage_label%": "Interface Language",
"%settings_platform_ptxUtilsMementoData_label%": "PtxUtils Memento Data",
"%settings_platform_paratextDataLastRegistryDataCachedTimes_label%": "ParatextData Last Registry Data Cached Times",
"%project_settings_platform_group1_label%": "Platform Settings",
"%project_settings_platform_group1_description%": "Project settings pertaining to the software overall",
"%project_settings_platform_name_label%": "Project Short Name",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public override async Task TestSetup()
[TestCase("12345", "System.ArgumentException: Input must have even number of characters")]
[TestCase(
"abcdefgh",
"System.ArgumentException: String must contain only hexadecimal characters: abcdefgh"
"System.ArgumentException: String must contain only hexadecimal characters: ABCDEFGH"
)]
public async Task InvalidProjectId_ReturnsError(string projectId, string startOfError)
{
Expand Down
2 changes: 1 addition & 1 deletion c-sharp-tests/c-sharp-tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="ParatextData" Version="9.5.0.5" />
<PackageReference Include="ParatextData" Version="9.5.0.6" />
</ItemGroup>

<ItemGroup>
Expand Down
5 changes: 4 additions & 1 deletion c-sharp/Messages/MessageRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ namespace Paranext.DataProvider.Messages;
[JsonMessageDeserialization(MessageField.MESSAGE_TYPE, MessageType.REQUEST)]
public sealed class MessageRequest : Message
{
private static readonly JsonSerializerOptions s_serializerOptions =
SerializationOptions.CreateSerializationOptions();

/// <summary>
/// ONLY FOR DESERIALIZATION
/// </summary>
Expand All @@ -24,7 +27,7 @@ public MessageRequest(string requestType, int requestId, object contents)
{
RequestType = requestType;
RequestId = requestId;
Contents = JsonSerializer.SerializeToElement(contents);
Contents = JsonSerializer.SerializeToElement(contents, s_serializerOptions);
}

public MessageRequest(string requestType, int requestId, JsonElement contents)
Expand Down
2 changes: 1 addition & 1 deletion c-sharp/ParanextDataProvider.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="ParatextData" Version="9.5.0.5" />
<PackageReference Include="ParatextData" Version="9.5.0.6" />
<PackageReference Include="SIL.Core" Version="14.2.0-beta0009" />
<PackageReference Include="SIL.Scripture" Version="14.2.0-beta0009" />
<PackageReference Include="SIL.WritingSystems" Version="14.2.0-beta0009" />
Expand Down
7 changes: 7 additions & 0 deletions c-sharp/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
using Paranext.DataProvider.MessageTransports;
using Paranext.DataProvider.NetworkObjects;
using Paranext.DataProvider.Projects;
using Paranext.DataProvider.Services;
using Paratext.Data;
using PtxUtils;

namespace Paranext.DataProvider;
Expand All @@ -24,6 +26,11 @@ public static async Task Main()
}

var paratextProjects = new LocalParatextProjects();

// Adapted from Paratext's `Program.StaticInitialization`
ParatextDataSettings.Initialize(new PersistedParatextDataSettings(papi));
PtxUtilsDataSettings.Initialize(new PersistedPtxUtilsSettings(papi));

var paratextFactory = new ParatextProjectDataProviderFactory(papi, paratextProjects);
await Task.WhenAll(paratextFactory.Initialize());

Expand Down
13 changes: 13 additions & 0 deletions c-sharp/Projects/ParatextProjectDataProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,19 @@ public ResponseToRequest ResetProjectSetting(string jsonKey)

#endregion

#region Scripture-related methods

/// <summary>
/// Send an event on the PAPI announcing that all the Scripture data has changed. This is used
/// for reloading all the Scripture, settings, etc. after a project has been S/Red.
/// </summary>
public void SendFullProjectUpdateEvent()
{
SendDataUpdateEvent("*");
}

#endregion

#region USFM

public ResponseToRequest GetBookUsfm(string jsonString)
Expand Down
16 changes: 16 additions & 0 deletions c-sharp/Projects/ParatextProjectDataProviderFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ protected override ResponseToRequest GetAvailableProjects()

protected override ResponseToRequest GetProjectDataProviderID(string projectID)
{
projectID = projectID.ToUpperInvariant();

// If we already have a PDP for this project, just return it
if (_pdpMap.TryGetValue(projectID, out var existingPdp))
return ResponseToRequest.Succeeded(existingPdp.DataProviderName);
Expand Down Expand Up @@ -91,4 +93,18 @@ protected override ResponseToRequest GetProjectDataProviderID(string projectID)
return ResponseToRequest.Succeeded(newPdp.DataProviderName);
}
}

/// <summary>
/// Get an existing PDP if it exists for a project id
/// </summary>
/// <param name="projectID"></param>
/// <returns></returns>
public ParatextProjectDataProvider? GetExistingProjectDataProvider(string projectID)
{
projectID = projectID.ToUpperInvariant();

if (_pdpMap.TryGetValue(projectID, out var existingPdp))
return existingPdp;
return null;
}
}
70 changes: 70 additions & 0 deletions c-sharp/Services/LocalizationService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using System.Diagnostics;
using System.Text.Json;
using Paranext.DataProvider.MessageTransports;

namespace Paranext.DataProvider.Services;

internal static class LocalizationService
{
public const string SETTINGS_SERVICE_NAME = "platform.localizationDataServiceDataProvider";
private const string SETTINGS_SERVICE_REQUEST = $"object:{SETTINGS_SERVICE_NAME}-data.function";

/// <summary>
/// Get a localized string value
/// </summary>
/// <param name="papiClient"></param>
/// <param name="key">localized string key `%something%`</param>
/// <param name="defaultValue">Default value if the key comes back as the value or the request fails</param>
/// <param name="shouldThrowErrors">if set to `true`, will throw errors instead of ignoring and returning default value. Defaults to `false`</param>
/// <returns></returns>
public static string GetLocalizedString(PapiClient papiClient, string key, string? defaultValue = null, bool shouldThrowErrors = false)
{
string value = defaultValue ?? key;
TaskCompletionSource taskSource = new();
using var getSettingTask = taskSource.Task;

papiClient.SendRequest(
SETTINGS_SERVICE_REQUEST,
new object[] { "getLocalizedString", new LocalizationSelector(key) },
(bool success, object? returnValue) =>
{
try
{
if (success)
{
var result = (JsonElement?)returnValue;
if (result.HasValue)
{
var resultString = result.Value.Deserialize<string>();
if (resultString != null && resultString != key)
value = resultString;
}
}

taskSource.TrySetResult();
}
catch (Exception ex)
{
if (shouldThrowErrors)
taskSource.TrySetException(ex);
else {
Trace.TraceError(ex.Message);
taskSource.TrySetResult();
}
}
}
);

using var cts = new CancellationTokenSource();
getSettingTask.Wait(cts.Token);
return value;
}
}

public class LocalizationSelector(string localizeKey)
{
/// <summary>
/// ID of the project (must be unique and case-insensitive)
/// </summary>
public string LocalizeKey { get; } = localizeKey;
}
22 changes: 22 additions & 0 deletions c-sharp/Services/PersistedParatextDataSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using Paranext.DataProvider.MessageTransports;
using Paratext.Data;
using PtxUtils;

namespace Paranext.DataProvider.Services;

internal class PersistedParatextDataSettings(PapiClient papiClient) : IParatextDataSettings
{
public SerializableStringDictionary LastRegistryDataCachedTimes { get; set; } = SettingsService.GetSettingObject<SerializableStringDictionary>(
papiClient,
Settings.PARATEXT_DATA_LAST_REGISTRY_DATA_CACHED_TIMES
) ?? [];

public void SafeSave()
{
SettingsService.SetSetting(
papiClient,
Settings.PARATEXT_DATA_LAST_REGISTRY_DATA_CACHED_TIMES,
LastRegistryDataCachedTimes
);
}
}
29 changes: 29 additions & 0 deletions c-sharp/Services/PersistedPtxUtilsSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Paranext.DataProvider.MessageTransports;
using PtxUtils;

namespace Paranext.DataProvider.Services;

internal class PersistedPtxUtilsSettings(PapiClient papiClient) : IPtxUtilsSettings
{
public SerializableStringDictionary MementoData { get; set;} = SettingsService.GetSettingObject<SerializableStringDictionary>(
papiClient,
Settings.PTX_UTILS_MEMENTO_DATA
) ?? [];

public bool UpgradeNeeded
{
get => throw new NotImplementedException();
set => throw new NotImplementedException();
}

public bool EnableFormSnapping
{
get => throw new NotImplementedException();
set => throw new NotImplementedException();
}

public void SafeSave()
{
SettingsService.SetSetting(papiClient, Settings.PTX_UTILS_MEMENTO_DATA, MementoData);
}
}
4 changes: 4 additions & 0 deletions c-sharp/Services/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ namespace Paranext.DataProvider.Services;

public sealed class Settings
{
public const string PARATEXT_DATA_LAST_REGISTRY_DATA_CACHED_TIMES =
"platform.paratextDataLastRegistryDataCachedTimes";
public const string PTX_UTILS_MEMENTO_DATA = "platform.ptxUtilsMementoData";

public const string INCLUDE_MY_PARATEXT_9_PROJECTS =
"platformScripture.includeMyParatext9Projects";
}
51 changes: 51 additions & 0 deletions c-sharp/Services/SettingsService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,55 @@ internal static class SettingsService
{
return GetSettingRaw(papiClient, key)?.Deserialize<T>();
}

public static bool SetSetting(PapiClient papiClient, string key, object? settingData)
{
TaskCompletionSource taskSource = new();
using var getSettingTask = taskSource.Task;

var didChangeData = false;

papiClient.SendRequest(
SETTINGS_SERVICE_REQUEST,
new object?[] { "set", key, settingData },
(bool success, object? returnValue) =>
{
try
{
if (success)
{
var result = (JsonElement?)returnValue;
if (result.HasValue)
{
try
{
if (result.Value.Deserialize<bool>())
didChangeData = true;
else
didChangeData = false;
}
catch (JsonException)
{
// If they sent a string data type name or an array of them, it will
// fail to deserialize. Interpret that as `didChangeData` true
// because pretty much anything but `false` means the data changed.
// See `DataProviderUpdateInstructions` for more info
didChangeData = true;
}
}
}

taskSource.TrySetResult();
}
catch (Exception ex)
{
taskSource.TrySetException(ex);
}
}
);

using var cts = new CancellationTokenSource();
getSettingTask.Wait(cts.Token);
return didChangeData;
}
}
4 changes: 2 additions & 2 deletions extensions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
"build:types": "cd .. && npm run build:types",
"start:core": "cd .. && npm run start",
"start": "npm run start:core",
"lint": "npm run lint:scripts && npm run lint:styles",
"lint:scripts": "cross-env NODE_ENV=development eslint --ext .cjs,.js,.jsx,.ts,.tsx --cache .",
"lint": "npm run lint:scripts --max-old-space-size=4096 && npm run lint:styles",
"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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ function ProjectSettingsEditor({
options={HTML_COLOR_NAMES}
// The value is one of the options, and all options are HTMLColorNames
// eslint-disable-next-line no-type-assertion/no-type-assertion
onChange={(_, value) => setHeaderColor?.(value as HTMLColorNames)}
width={200}
onChange={(value) => setHeaderColor?.(value as HTMLColorNames)}
/>
<button type="button" onClick={resetHeaderColor}>
Reset
Expand Down
22 changes: 22 additions & 0 deletions lib/papi-dts/papi.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,13 @@ declare module 'shared/models/web-view.model' {
* to function. The more you list, the higher the theoretical security risks.
*/
allowedFrameSources?: string[];
/**
* Whether to allow this iframe to open separate windows with window.open and anchor tags with
* `target="_blank"`. Setting this to true adds `allow-popups` to the WebView iframe's [sandbox
* attribute] (https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#sandbox). Defaults
* to `false`
*/
allowPopups?: boolean;
};
/** WebView representation using React */
export type WebViewDefinitionReact = WebViewDefinitionBase & {
Expand Down Expand Up @@ -171,6 +178,7 @@ declare module 'shared/models/web-view.model' {
'allowScripts',
'allowSameOrigin',
'allowedFrameSources',
'allowPopups',
];
/**
* The keys of properties on a WebViewDefinition that are omitted when converting to a
Expand Down Expand Up @@ -2380,6 +2388,20 @@ declare module 'papi-shared-types' {
interface SettingTypes {
'platform.verseRef': ScriptureReference;
'platform.interfaceLanguage': string[];
/**
* Mementos managed in the dotnet process and used for interacting with PtxUtils. Mementos are
* persisted objects containing some data. They are stored as xml strings.
*/
'platform.ptxUtilsMementoData': {
[key: string]: string;
};
/**
* Tracking last S/R registry data cache time managed in the dotnet process and used for
* interacting with ParatextData.
*/
'platform.paratextDataLastRegistryDataCachedTimes': {
[key: string]: string;
};
}
/**
* Names for each user setting available on the papi.
Expand Down
419 changes: 209 additions & 210 deletions lib/platform-bible-react/dist/index.cjs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion lib/platform-bible-react/dist/index.cjs.map

Large diffs are not rendered by default.

Loading

0 comments on commit c9a163c

Please sign in to comment.