diff --git a/.gitignore b/.gitignore index 44f520a4d..d53539bf9 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,4 @@ artifacts/ backend/FwLite/FwLiteShared/wwwroot/viewer *.csproj.user +*.log diff --git a/backend/FwLite/FwLiteMaui/AppVersion.cs b/backend/FwLite/FwLiteMaui/AppVersion.cs index a220d5997..f95cc5c8c 100644 --- a/backend/FwLite/FwLiteMaui/AppVersion.cs +++ b/backend/FwLite/FwLiteMaui/AppVersion.cs @@ -1,20 +1,9 @@ using System.Reflection; +using FwLiteShared.Services; namespace FwLiteMaui; public class AppVersion { - static AppVersion() - { - var infoVersion = typeof(AppVersion).Assembly - .GetCustomAttribute()?.InformationalVersion; - //info version may look like v2024-12-12-3073dd1c+3073dd1ce2ff5510f54a9411366f55c958b9ea45. We want to strip off everything after the +, so we can compare versions - if (infoVersion is not null && infoVersion.Contains('+')) - { - infoVersion = infoVersion[..infoVersion.IndexOf('+')]; - } - Version = infoVersion ?? "dev"; - } - - public static readonly string Version; + public static readonly string Version = VersionHelper.DisplayVersion(typeof(AppVersion).Assembly); } diff --git a/backend/FwLite/FwLiteMaui/FwLiteMauiKernel.cs b/backend/FwLite/FwLiteMaui/FwLiteMauiKernel.cs index c1438d643..61dc04d22 100644 --- a/backend/FwLite/FwLiteMaui/FwLiteMauiKernel.cs +++ b/backend/FwLite/FwLiteMaui/FwLiteMauiKernel.cs @@ -41,7 +41,7 @@ public static void AddFwLiteMauiServices(this IServiceCollection services, FwLiteProjectSync.FwLiteProjectSyncKernel.AddFwLiteProjectSync(services); #endif #if WINDOWS - services.AddFwLiteWindows(); + services.AddFwLiteWindows(env); #endif #if ANDROID services.Configure(config => config.ParentActivityOrWindow = Platform.CurrentActivity); @@ -51,6 +51,30 @@ public static void AddFwLiteMauiServices(this IServiceCollection services, var window = Application.Current?.Windows.FirstOrDefault(); if (window is not null) Application.Current?.ActivateWindow(window); }); + services.Configure(config => + { + config.AppVersion = AppVersion.Version; + if (DeviceInfo.Current.Platform == DevicePlatform.Android) + { + config.Os = FwLitePlatform.Android; + } + else if (DeviceInfo.Current.Platform == DevicePlatform.iOS) + { + config.Os = FwLitePlatform.iOS; + } + else if (DeviceInfo.Current.Platform == DevicePlatform.macOS) + { + config.Os = FwLitePlatform.Mac; + } + else if (DeviceInfo.Current.Platform == DevicePlatform.WinUI) + { + config.Os = FwLitePlatform.Windows; + } + else + { + config.Os = FwLitePlatform.Other; + } + }); var defaultDataPath = IsPortableApp ? Directory.GetCurrentDirectory() : FileSystem.AppDataDirectory; var baseDataPath = Path.GetFullPath(configuration.GetSection("FwLiteMaui").GetValue("BaseDataDir") ?? diff --git a/backend/FwLite/FwLiteMaui/Platforms/Windows/WindowsKernel.cs b/backend/FwLite/FwLiteMaui/Platforms/Windows/WindowsKernel.cs index c04fa867c..ddf92c248 100644 --- a/backend/FwLite/FwLiteMaui/Platforms/Windows/WindowsKernel.cs +++ b/backend/FwLite/FwLiteMaui/Platforms/Windows/WindowsKernel.cs @@ -1,10 +1,12 @@ using System.Runtime.InteropServices; +using FwLiteShared; +using Microsoft.Extensions.Hosting; namespace FwLiteMaui; public static class WindowsKernel { - public static void AddFwLiteWindows(this IServiceCollection services) + public static void AddFwLiteWindows(this IServiceCollection services, IHostEnvironment environment) { if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) return; if (!FwLiteMauiKernel.IsPortableApp) @@ -12,5 +14,9 @@ public static void AddFwLiteWindows(this IServiceCollection services) services.AddSingleton(); services.AddSingleton(); } + services.Configure(config => + { + config.UseDevAssets = environment.IsDevelopment(); + }); } } diff --git a/backend/FwLite/FwLiteMaui/app.log b/backend/FwLite/FwLiteMaui/app.log deleted file mode 100644 index 60ab44bec..000000000 --- a/backend/FwLite/FwLiteMaui/app.log +++ /dev/null @@ -1,762 +0,0 @@ -2024-12-20T12:07:09.1711028+01:00 INFO [FwLiteMaui.FwLiteMauiKernel.HostedServiceAdapter] [0] Initializing hosted services -2024-12-20T12:07:09.1837950+01:00 INFO [Microsoft.Maui.Hosting.MauiApp] [0] App started -2024-12-20T12:07:10.7162653+01:00 WARN [Microsoft.EntityFrameworkCore.Model.Validation] [Microsoft.EntityFrameworkCore.Infrastructure.SensitiveDataLoggingEnabledWarning] Sensitive data logging is enabled. Log entries and exception messages may include sensitive application data; this mode should only be enabled during development. -2024-12-20T12:07:10.7616818+01:00 WARN [Microsoft.EntityFrameworkCore.Model.Validation] [Microsoft.EntityFrameworkCore.Model.Validation.CollectionWithoutComparer] The property 'Entry.ComplexFormTypes' is a collection or enumeration type with a value converter but with no value comparer. Set a value comparer to ensure the collection/enumeration elements are compared correctly. -2024-12-20T12:07:10.7753168+01:00 WARN [Microsoft.EntityFrameworkCore.Model.Validation] [Microsoft.EntityFrameworkCore.Model.Validation.CollectionWithoutComparer] The property 'Sense.SemanticDomains' is a collection or enumeration type with a value converter but with no value comparer. Set a value comparer to ensure the collection/enumeration elements are compared correctly. -2024-12-20T12:07:10.7762131+01:00 WARN [Microsoft.EntityFrameworkCore.Model.Validation] [Microsoft.EntityFrameworkCore.Model.Validation.CollectionWithoutComparer] The property 'WritingSystem.Exemplars' is a collection or enumeration type with a value converter but with no value comparer. Set a value comparer to ensure the collection/enumeration elements are compared correctly. -2024-12-20T12:07:11.6868159+01:00 WARN [Microsoft.EntityFrameworkCore.Query] [Microsoft.EntityFrameworkCore.Query.FirstWithoutOrderByAndFilterWarning] The query uses the 'First'/'FirstOrDefault' operator without 'OrderBy' and filter operators. This may lead to unpredictable results. -2024-12-20T12:07:12.5096795+01:00 INFO [FwLiteShared.Services.FwLiteProvider] [0] Clearing Service MiniLcmApi -2024-12-20T12:07:12.5300026+01:00 INFO [FwLiteShared.Layout.SvelteLayout] [0] OnAfterRenderAsync SvelteLayout -2024-12-20T12:07:12.6588751+01:00 WARN [FwLiteShared.Sync.SyncService] [0] Project tke-flex----temp has no origin domain, unable to create http sync client -2024-12-20T12:07:16.2316335+01:00 INFO [FwLiteShared.Layout.SvelteLayout] [0] OnAfterRenderAsync SvelteLayout -2024-12-20T12:07:17.3640980+01:00 INFO [LinqToDB.Data.DataConnection] [0] BeforeExecute -BeginTransactionAsync(Serializable) -2024-12-20T12:07:17.3698736+01:00 INFO [LinqToDB.Data.DataConnection] [0] Query Execution Time (AfterExecute) (async): 00:00:00.0075826 - -2024-12-20T12:07:17.4338803+01:00 INFO [LinqToDB.Data.DataConnection] [0] BeforeExecute --- SQLite.MS SQLite (asynchronously) -DECLARE @WsId NVarChar(3) -- String -SET @WsId = 'tke' -DECLARE @take -- Int32 -SET @take = 1000 - -SELECT - [lw_Sense].[Id_1], - [lw_Sense].[Id], - [detail_1].[Id], - [detail_1].[Sentence], - [detail_1].[Translation], - [detail_1].[Reference], - [detail_1].[SenseId], - [detail_1].[DeletedAt] -FROM - ( - SELECT DISTINCT - [detail].[Id], - [lw_Entry].[Id] as [Id_1] - FROM - ( - SELECT DISTINCT - [t2].[Id] - FROM - ( - SELECT - [t1].[Id] - FROM - [Entry] [t1] - ORDER BY - Trim(CASE - WHEN ([t1].[CitationForm]->>@WsId IS NULL OR Length([t1].[CitationForm]->>@WsId) = 0) - THEN [t1].[LexemeForm]->>@WsId - ELSE [t1].[CitationForm]->>@WsId - END) COLLATE NOCASE_WS_tke, - [t1].[Id] - LIMIT @take - ) [t2] - ) [lw_Entry] - INNER JOIN [Sense] [detail] ON [lw_Entry].[Id] = [detail].[EntryId] - ) [lw_Sense] - INNER JOIN [ExampleSentence] [detail_1] ON [lw_Sense].[Id] = [detail_1].[SenseId] - -2024-12-20T12:07:17.4796139+01:00 INFO [LinqToDB.Data.DataConnection] [0] Query Execution Time (AfterExecute) (async): 00:00:00.0478382 - -2024-12-20T12:07:17.6066893+01:00 INFO [LinqToDB.Data.DataConnection] [0] Total Execution Time (Completed) (async): 00:00:00.2283913. Rows Count: 114. - -2024-12-20T12:07:17.6082412+01:00 INFO [LinqToDB.Data.DataConnection] [0] BeforeExecute --- SQLite.MS SQLite (asynchronously) -DECLARE @WsId NVarChar(3) -- String -SET @WsId = 'tke' -DECLARE @take -- Int32 -SET @take = 1000 - -SELECT - [lw_Entry].[Id], - [detail].[Id], - [detail].[Order], - [detail].[DeletedAt], - [detail].[EntryId], - [detail].[Definition], - [detail].[Gloss], - [detail].[PartOfSpeech], - [detail].[PartOfSpeechId], - [detail].[SemanticDomains] -FROM - ( - SELECT DISTINCT - [t2].[Id] - FROM - ( - SELECT - [t1].[Id] - FROM - [Entry] [t1] - ORDER BY - Trim(CASE - WHEN ([t1].[CitationForm]->>@WsId IS NULL OR Length([t1].[CitationForm]->>@WsId) = 0) - THEN [t1].[LexemeForm]->>@WsId - ELSE [t1].[CitationForm]->>@WsId - END) COLLATE NOCASE_WS_tke, - [t1].[Id] - LIMIT @take - ) [t2] - ) [lw_Entry] - INNER JOIN [Sense] [detail] ON [lw_Entry].[Id] = [detail].[EntryId] - -2024-12-20T12:07:17.6277740+01:00 FAIL [LinqToDB.Data.DataConnection] [0] Error -Exception: Microsoft.Data.Sqlite.SqliteException -Message : SQLite Error 1: 'no such column: detail.Order'. - at Microsoft.Data.Sqlite.SqliteException.ThrowExceptionForRC(Int32 rc, sqlite3 db) - at Microsoft.Data.Sqlite.SqliteCommand.PrepareAndEnumerateStatements()+MoveNext() - at Microsoft.Data.Sqlite.SqliteCommand.GetStatements()+MoveNext() - at Microsoft.Data.Sqlite.SqliteDataReader.NextResult() - at Microsoft.Data.Sqlite.SqliteCommand.ExecuteReader(CommandBehavior behavior) - at Microsoft.Data.Sqlite.SqliteCommand.ExecuteReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken) - at Microsoft.Data.Sqlite.SqliteCommand.ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken) - at LinqToDB.Data.DataConnection.ExecuteReaderAsync(CommandBehavior commandBehavior, CancellationToken cancellationToken) - at LinqToDB.Data.DataConnection.ExecuteReaderAsync(CommandBehavior commandBehavior, CancellationToken cancellationToken) - at LinqToDB.Data.DataConnection.ExecuteDataReaderAsync(CommandBehavior commandBehavior, CancellationToken cancellationToken) - at LinqToDB.Data.DataConnection.ExecuteDataReaderAsync(CommandBehavior commandBehavior, CancellationToken cancellationToken) - -2024-12-20T12:07:17.6281676+01:00 INFO [LinqToDB.Data.DataConnection] [0] Total Execution Time (Completed) (async): 00:00:00.0208818. Rows Count: 0. - -2024-12-20T12:07:17.6302429+01:00 INFO [LinqToDB.Data.DataConnection] [0] BeforeExecute -DisposeTransactionAsync -2024-12-20T12:07:17.6319031+01:00 INFO [LinqToDB.Data.DataConnection] [0] Query Execution Time (AfterExecute) (async): 00:00:00.0016527 - -2024-12-20T12:08:02.3366695+01:00 INFO [FwLiteShared.Services.FwLiteProvider] [0] Clearing Service MiniLcmApi -2024-12-20T12:08:02.3475849+01:00 INFO [FwLiteShared.Layout.SvelteLayout] [0] OnAfterRenderAsync SvelteLayout -2024-12-20T12:08:09.7923610+01:00 INFO [FwLiteShared.Services.FwLiteProvider] [0] Clearing Service MiniLcmApi -2024-12-20T12:08:09.7944776+01:00 INFO [FwLiteShared.Layout.SvelteLayout] [0] OnAfterRenderAsync SvelteLayout -2024-12-20T12:08:52.9084959+01:00 INFO [Microsoft.Maui.Hosting.MauiApp] [0] Disposing app -2024-12-20T12:08:52.9181912+01:00 FAIL [Microsoft.Maui.Hosting.MauiApp] [0] Unhandled exceptionSystem.ObjectDisposedException: Cannot access a disposed object. -Object name: 'IServiceProvider'. - at Microsoft.Extensions.DependencyInjection.ServiceLookup.ThrowHelper.ThrowObjectDisposedException() - at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(ServiceIdentifier serviceIdentifier, ServiceProviderEngineScope serviceProviderEngineScope) - at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType) - at Microsoft.Maui.MauiContext.WrappedServiceProvider.GetService(Type serviceType) - at Microsoft.Maui.LifecycleEvents.LifecycleEventServiceExtensions.GetLifecycleEventDelegates[TDelegate](IServiceProvider services, String eventName)+MoveNext() - at Microsoft.Maui.LifecycleEvents.LifecycleEventServiceExtensions.InvokeLifecycleEvents[TDelegate](IServiceProvider services, Action`1 action) - at Microsoft.Maui.MauiWinUIWindow.g__OnWindowMessage|14_1(Object sender, WindowMessageEventArgs e) - at Microsoft.Maui.ApplicationModel.WindowMessageManager.NewWindowProc(IntPtr hWnd, UInt32 uMsg, IntPtr wParam, IntPtr lParam) - -2024-12-20T12:08:52.9492051+01:00 INFO [FwDataMiniLcmBridge.FwDataFactory] [0] Closing all projects -2024-12-20T12:09:51.1835145+01:00 INFO [FwLiteMaui.FwLiteMauiKernel.HostedServiceAdapter] [0] Initializing hosted services -2024-12-20T12:09:51.1941049+01:00 INFO [Microsoft.Maui.Hosting.MauiApp] [0] App started -2024-12-20T12:09:52.9950166+01:00 INFO [FwLiteShared.Services.FwLiteProvider] [0] Clearing Service MiniLcmApi -2024-12-20T12:09:53.0256130+01:00 INFO [FwLiteShared.Layout.SvelteLayout] [0] OnAfterRenderAsync SvelteLayout -2024-12-20T12:10:01.0904175+01:00 INFO [FwDataMiniLcmBridge.FwDataFactory] [0] Loading project tke-flex----temp.fwdata -2024-12-20T12:10:08.4855723+01:00 INFO [FwDataMiniLcmBridge.FwDataFactory] [0] Project tke-flex----temp.fwdata loaded -2024-12-20T12:10:09.1107179+01:00 WARN [Microsoft.EntityFrameworkCore.Model.Validation] [Microsoft.EntityFrameworkCore.Infrastructure.SensitiveDataLoggingEnabledWarning] Sensitive data logging is enabled. Log entries and exception messages may include sensitive application data; this mode should only be enabled during development. -2024-12-20T12:10:09.1293815+01:00 WARN [Microsoft.EntityFrameworkCore.Model.Validation] [Microsoft.EntityFrameworkCore.Model.Validation.CollectionWithoutComparer] The property 'Entry.ComplexFormTypes' is a collection or enumeration type with a value converter but with no value comparer. Set a value comparer to ensure the collection/enumeration elements are compared correctly. -2024-12-20T12:10:09.1356854+01:00 WARN [Microsoft.EntityFrameworkCore.Model.Validation] [Microsoft.EntityFrameworkCore.Model.Validation.CollectionWithoutComparer] The property 'Sense.SemanticDomains' is a collection or enumeration type with a value converter but with no value comparer. Set a value comparer to ensure the collection/enumeration elements are compared correctly. -2024-12-20T12:10:09.1359421+01:00 WARN [Microsoft.EntityFrameworkCore.Model.Validation] [Microsoft.EntityFrameworkCore.Model.Validation.CollectionWithoutComparer] The property 'WritingSystem.Exemplars' is a collection or enumeration type with a value converter but with no value comparer. Set a value comparer to ensure the collection/enumeration elements are compared correctly. -2024-12-20T12:10:09.4702438+01:00 FAIL [Microsoft.EntityFrameworkCore.Database.Command] [Microsoft.EntityFrameworkCore.Database.Command.CommandError] Failed executing DbCommand (7ms) [Parameters=[], CommandType='Text', CommandTimeout='30'] -SELECT "w"."Id", "w"."Abbreviation", "w"."DeletedAt", "w"."Exemplars", "w"."Font", "w"."Name", "w"."Order", "w"."SnapshotId", "w"."Type", "w"."WsId" -FROM "WritingSystem" AS "w" -2024-12-20T12:10:09.4860140+01:00 FAIL [Microsoft.EntityFrameworkCore.Query] [Microsoft.EntityFrameworkCore.Query.QueryIterationFailed] An exception occurred while iterating over the results of a query for context type 'LcmCrdt.LcmCrdtDbContext'. -Microsoft.Data.Sqlite.SqliteException (0x80004005): SQLite Error 1: 'no such table: WritingSystem'. - at Microsoft.Data.Sqlite.SqliteException.ThrowExceptionForRC(Int32 rc, sqlite3 db) - at Microsoft.Data.Sqlite.SqliteCommand.PrepareAndEnumerateStatements()+MoveNext() - at Microsoft.Data.Sqlite.SqliteCommand.GetStatements()+MoveNext() - at Microsoft.Data.Sqlite.SqliteDataReader.NextResult() - at Microsoft.Data.Sqlite.SqliteCommand.ExecuteReader(CommandBehavior behavior) - at Microsoft.Data.Sqlite.SqliteCommand.ExecuteDbDataReader(CommandBehavior behavior) - at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject) - at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.InitializeReader(Enumerator enumerator) - at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.<>c.b__21_0(DbContext _, Enumerator enumerator) - at Microsoft.EntityFrameworkCore.Storage.NonRetryingExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded) - at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()Microsoft.Data.Sqlite.SqliteException (0x80004005): SQLite Error 1: 'no such table: WritingSystem'. - at Microsoft.Data.Sqlite.SqliteException.ThrowExceptionForRC(Int32 rc, sqlite3 db) - at Microsoft.Data.Sqlite.SqliteCommand.PrepareAndEnumerateStatements()+MoveNext() - at Microsoft.Data.Sqlite.SqliteCommand.GetStatements()+MoveNext() - at Microsoft.Data.Sqlite.SqliteDataReader.NextResult() - at Microsoft.Data.Sqlite.SqliteCommand.ExecuteReader(CommandBehavior behavior) - at Microsoft.Data.Sqlite.SqliteCommand.ExecuteDbDataReader(CommandBehavior behavior) - at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject) - at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.InitializeReader(Enumerator enumerator) - at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.<>c.b__21_0(DbContext _, Enumerator enumerator) - at Microsoft.EntityFrameworkCore.Storage.NonRetryingExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded) - at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext() - -2024-12-20T12:10:09.5921596+01:00 WARN [Microsoft.EntityFrameworkCore.Model.Validation] [Microsoft.EntityFrameworkCore.Model.Validation.CollectionWithoutComparer] The property 'Entry.ComplexFormTypes' is a collection or enumeration type with a value converter but with no value comparer. Set a value comparer to ensure the collection/enumeration elements are compared correctly. -2024-12-20T12:10:09.5930789+01:00 WARN [Microsoft.EntityFrameworkCore.Model.Validation] [Microsoft.EntityFrameworkCore.Model.Validation.CollectionWithoutComparer] The property 'Sense.SemanticDomains' is a collection or enumeration type with a value converter but with no value comparer. Set a value comparer to ensure the collection/enumeration elements are compared correctly. -2024-12-20T12:10:09.5933584+01:00 WARN [Microsoft.EntityFrameworkCore.Model.Validation] [Microsoft.EntityFrameworkCore.Model.Validation.CollectionWithoutComparer] The property 'WritingSystem.Exemplars' is a collection or enumeration type with a value converter but with no value comparer. Set a value comparer to ensure the collection/enumeration elements are compared correctly. -2024-12-20T12:10:09.9137251+01:00 WARN [Microsoft.EntityFrameworkCore.Query] [Microsoft.EntityFrameworkCore.Query.FirstWithoutOrderByAndFilterWarning] The query uses the 'First'/'FirstOrDefault' operator without 'OrderBy' and filter operators. This may lead to unpredictable results. -2024-12-20T12:10:12.0914087+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported ws en -2024-12-20T12:10:12.1289810+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported ws pt-PT -2024-12-20T12:10:12.1387144+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported ws tke -2024-12-20T12:10:12.1493189+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported ws tke-fonipa -2024-12-20T12:10:12.2579089+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 2d2f1046-2a28-4be5-9165-9abcc1ec0ece -2024-12-20T12:10:12.2711682+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 28486d4e-6c8c-4b7c-8845-2715f6773e43 -2024-12-20T12:10:12.2853984+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 5d8e66d5-1ebf-49b6-a222-81985362ef4a -2024-12-20T12:10:12.2975996+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech e9585956-043e-47d0-a21a-d294642ceaf2 -2024-12-20T12:10:12.3096628+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech cf028edd-f83c-4bd2-a5db-a8d1c097f1be -2024-12-20T12:10:12.3200142+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 153ac115-4a1f-4ffd-93c7-01de103bce3b -2024-12-20T12:10:12.3323681+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 2b2c416f-67d0-48f0-89d7-3a35e9676a54 -2024-12-20T12:10:12.3471873+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 4870c6ef-59d7-4b6e-8d51-1cd3469bee16 -2024-12-20T12:10:12.3639412+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 97af568e-459f-44b4-a51e-9be17115d066 -2024-12-20T12:10:12.3745194+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 0a446b0b-a8d3-4d44-b91d-1c0281f66bcb -2024-12-20T12:10:12.3878356+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech ad7a835f-73d4-4702-b6ec-fb3db1f5ff5c -2024-12-20T12:10:12.4008312+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech d86aead9-ce13-4a3f-8361-4b349002be32 -2024-12-20T12:10:12.4137588+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 4f2ab39b-1c8f-4c88-9c9b-66c53dd7b559 -2024-12-20T12:10:12.4341947+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech aa2b559d-cedd-41e8-8dee-08e761244354 -2024-12-20T12:10:12.4493961+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 1d80b567-652c-4190-b108-4d361da7720f -2024-12-20T12:10:12.4627482+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 1fa0558e-2bb9-41a3-85e0-5409bc8692ae -2024-12-20T12:10:12.4807601+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 4a7f8375-5563-48ad-a1e2-50eb5ca74c62 -2024-12-20T12:10:12.4975266+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 87cf3043-78cd-4721-9c0a-ea13d74de706 -2024-12-20T12:10:12.5185499+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech e0eb1d6f-2cdf-4ca4-8c14-a5cbdaf78266 -2024-12-20T12:10:12.5393250+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 7f71d182-e5f4-4b30-88c8-01ffc3591e85 -2024-12-20T12:10:12.5578267+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech e9213c9c-adee-4f76-99a5-a553f3ce00a8 -2024-12-20T12:10:12.5937007+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 45fe03f0-b040-4eec-9079-df36f6af9db7 -2024-12-20T12:10:12.6148301+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 7ea2c1ba-de2e-428b-816d-b4cf5fc0af11 -2024-12-20T12:10:12.6427327+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech f906321a-d045-46b3-85ad-e6dfa27cd7c6 -2024-12-20T12:10:12.6645552+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 1b3fd084-0c99-491a-879f-afd211f84e8a -2024-12-20T12:10:12.6831431+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 3663471e-c221-4a9a-aa5a-a97c6bba3264 -2024-12-20T12:10:12.7077770+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 43442797-7e84-42e6-a956-a6322d00947f -2024-12-20T12:10:12.7336583+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 800de546-03a2-4620-bc8f-26750035a138 -2024-12-20T12:10:12.7552353+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 0f2c114c-cbb4-408d-ac87-8eb16c902100 -2024-12-20T12:10:12.7817622+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 2086ea2d-03c9-4b6e-b944-437695aaaa78 -2024-12-20T12:10:12.8083098+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 91ce1f01-da1a-4724-b281-f9b56b312980 -2024-12-20T12:10:12.8328535+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech b9a11ca7-3b60-4afd-8ca9-8a30c1468e13 -2024-12-20T12:10:12.8560232+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 29ae8acf-c0f6-49ab-9189-b4babc42e8f8 -2024-12-20T12:10:12.8795249+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 45603854-3b82-4de1-b6a9-dfce5d508565 -2024-12-20T12:10:12.9003753+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 32cf9e08-51bb-42c4-8340-6d614f7b6222 -2024-12-20T12:10:12.9206269+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 5efcfd42-becf-43f5-ad39-2a40be4402d3 -2024-12-20T12:10:12.9460950+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech ad5ec8c0-c55b-4ee9-bbd2-d109d436fa33 -2024-12-20T12:10:12.9642386+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 614a0435-42ed-428b-a2f9-5f2e44bd4e24 -2024-12-20T12:10:12.9851665+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 2ed23e4b-146a-41c8-b6ac-55f24b278f51 -2024-12-20T12:10:13.0129262+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 1d43b6e6-086e-4884-91c7-f8cfba05d449 -2024-12-20T12:10:13.0366217+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech c7fa8b45-219c-464f-8e48-8895f5bfb3af -2024-12-20T12:10:13.0575274+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 7550cdfc-5255-4c41-b2f1-24cea89f0ee2 -2024-12-20T12:10:13.0812135+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 97b55da7-2860-47b4-9ae9-d30c4dfbee43 -2024-12-20T12:10:13.0997025+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 82eb0f73-9f55-41df-8db3-00b191671289 -2024-12-20T12:10:13.1189444+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 5746eebe-2dd4-4c93-bb91-9f1b2813e50b -2024-12-20T12:10:13.1407009+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech f062b166-8303-4885-a5ca-486928e6f22d -2024-12-20T12:10:13.1582877+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 8567ab6e-71fa-4868-a127-481e493edbd2 -2024-12-20T12:10:13.1752934+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech c9444519-bbb3-4373-80e6-5f6f327c449c -2024-12-20T12:10:13.1941602+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech d0307592-bbd2-42b0-a751-4b999e3eefcd -2024-12-20T12:10:13.2136490+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 404ef895-01f2-4976-8703-11740f9ae526 -2024-12-20T12:10:13.2349182+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech e855c0fd-c170-461e-acf6-10e7a1298cf6 -2024-12-20T12:10:13.2565969+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 86752f1f-8622-4c26-852a-d46cd023a21b -2024-12-20T12:10:13.2764377+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech bdd5a2ab-51f4-4ccb-add0-0dc142eadb5e -2024-12-20T12:10:13.2970059+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 6970683c-0a98-4d9f-8808-7c9866b88754 -2024-12-20T12:10:13.3163684+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech ade71bca-7101-4ccf-8012-e6a876bb0e94 -2024-12-20T12:10:13.3374533+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 4798d643-a0ef-4a54-a6c7-df1b57ef362d -2024-12-20T12:10:13.3570516+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 5e64fd56-b3e8-467f-b141-f33b82bd9368 -2024-12-20T12:10:13.3889495+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech ef55fcb9-5ab3-4a34-bbdb-d861c8e859bf -2024-12-20T12:10:13.4102067+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 19fd6e29-a7f0-4714-b644-4e6347c0a06a -2024-12-20T12:10:13.4310061+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech b8c085a8-2713-4906-9b9a-f7b133359168 -2024-12-20T12:10:13.4551313+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech ed8d0320-c0a1-45f9-a4f1-533d9a2b306c -2024-12-20T12:10:13.4749099+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 3a6a7a55-9899-4739-b8fa-96c877371bb4 -2024-12-20T12:10:13.4947022+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech defba67b-bfb5-4965-8537-9aa1d1ddca0d -2024-12-20T12:10:13.5149868+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 782c475a-665f-4be8-9adc-80921a0b0d25 -2024-12-20T12:10:13.5368228+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech ecf3409a-27c8-42b6-83ba-5755291cec9a -2024-12-20T12:10:13.5579477+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech f84dd96b-256a-4753-8ebb-44474f9d09ab -2024-12-20T12:10:13.5799910+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 4180efe6-56e1-478b-b46c-9e7cc9fef315 -2024-12-20T12:10:13.6031613+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 7db012af-39d5-425e-ac35-9720d003a2e4 -2024-12-20T12:10:13.6295926+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 34b62f89-e73a-4b1e-9973-b74386733145 -2024-12-20T12:10:13.6512030+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech f0aafea8-fb72-43f1-bb84-eea2b82d5ad8 -2024-12-20T12:10:13.6718023+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech c179a2e2-83fd-4eb6-8252-f3cf795af30b -2024-12-20T12:10:13.6961247+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech cb40ea93-3f51-457a-a41a-a1b7ee7e6d8a -2024-12-20T12:10:13.7259510+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 80eb1f8b-992d-42a8-b6f1-5a80fd4e9840 -2024-12-20T12:10:13.7679542+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech cee2ba12-6c8c-4811-a408-d847fb9a7dfe -2024-12-20T12:10:13.8003538+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 36795fd6-070b-4308-a1cb-322ea638620b -2024-12-20T12:10:13.8507854+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 1601abc8-c374-42fa-b7f7-694a20a73808 -2024-12-20T12:10:13.9103230+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 2ae7b255-4968-4a14-9b46-78282328808f -2024-12-20T12:10:13.9484718+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 49d6f87e-353d-491b-95d6-2b60c5f8cf8d -2024-12-20T12:10:14.0323579+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech e8fa935f-1e7b-44f7-8bf3-ece862d4f372 -2024-12-20T12:10:14.1131683+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech c6441ef1-1a40-4381-9687-6f2b2db9a715 -2024-12-20T12:10:14.1898561+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 34b91305-750d-4240-ae9c-7313d4b9c64d -2024-12-20T12:10:14.2511382+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech f474f4eb-4010-4b47-9495-62ecbaac698b -2024-12-20T12:10:14.3208544+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech c0cbbc84-f869-4d47-98f3-9932f87fab9b -2024-12-20T12:10:14.3944399+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 6a6d48ea-1e87-4f90-a681-4fb9d9dc6f3b -2024-12-20T12:10:14.4626668+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 832c1761-2139-42ff-84d4-18871f27c52a -2024-12-20T12:10:14.5404618+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 0fb6585c-0497-419b-9fb5-4a8228e97011 -2024-12-20T12:10:14.5933510+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech a2c01e54-94c7-4e4e-8d17-bf1414bc437a -2024-12-20T12:10:14.6347184+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 056bf577-d33c-483a-92aa-3b669862a9ed -2024-12-20T12:10:14.6707448+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 123285e6-d521-4982-b02b-ae622de9e77c -2024-12-20T12:10:14.7103864+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 2142e362-f6f0-4e30-8f17-c6ff339efc60 -2024-12-20T12:10:14.7639688+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 4ee3b5f9-cd4c-41f5-b819-75a829e3f9d9 -2024-12-20T12:10:14.8135596+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech d0727f82-819d-4469-8f55-32647528d3d5 -2024-12-20T12:10:14.8655917+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 7e401e8d-92e4-4f0f-afd1-3a5ca6f02da7 -2024-12-20T12:10:14.9167958+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 10456a66-153a-4521-9640-de17006176be -2024-12-20T12:10:14.9586442+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 57518bc2-3f69-4708-b5de-065f7bafaa22 -2024-12-20T12:10:14.9968326+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 1f6bfa1e-e057-46e9-9326-557d18edc751 -2024-12-20T12:10:15.0376193+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 52592316-1c07-4a78-a4c2-9154d13efe8b -2024-12-20T12:10:15.0786963+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 1b4576ba-64a1-49dd-b70c-df3fbc4590f6 -2024-12-20T12:10:15.1307116+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 251b41bd-7f01-4bf7-a99a-9407d75bfa67 -2024-12-20T12:10:15.2193868+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 6fb06f21-5c30-4d9a-b216-149b2bb02943 -2024-12-20T12:10:15.2764386+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 21492972-edad-4281-ae05-3a574ba90547 -2024-12-20T12:10:15.3311026+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 241c2cd6-737a-4ea9-a9aa-fa37a84ee3e7 -2024-12-20T12:10:15.3814423+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 0f011a19-23d5-4109-84f1-3d4d9e603630 -2024-12-20T12:10:15.4393272+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech bbc5c95d-ffb6-40a9-a0a0-ca9b9839c8b5 -2024-12-20T12:10:15.4968606+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 0782f903-61f9-4263-98f7-2ad79fd33006 -2024-12-20T12:10:15.5589319+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 48c465a1-63f7-4da2-9f28-e62ae88d9c16 -2024-12-20T12:10:15.6343999+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 1f9e1307-58cf-4de1-9b5b-3db11e827e57 -2024-12-20T12:10:15.7026066+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 2a42e456-e213-4202-916b-cdccd59a8c0f -2024-12-20T12:10:15.7884317+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech cebce7f9-7834-4309-931e-42dd02bb8eea -2024-12-20T12:10:15.8603995+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 9a25c75a-210a-420c-8c5a-95bf2e2db4c6 -2024-12-20T12:10:15.9201228+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 05291780-738b-457f-9125-44b1d5481f0e -2024-12-20T12:10:15.9849334+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 1d625614-e3af-4047-8bd6-18ac7ab97ffe -2024-12-20T12:10:16.0332390+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 9b4f2ba8-2212-43b4-b759-e24b25f4cf79 -2024-12-20T12:10:16.0773718+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 94b958ce-4aed-4e34-90a8-4032d0c13b52 -2024-12-20T12:10:16.1403938+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 201717b3-078f-4ca7-852c-baecfd4f5581 -2024-12-20T12:10:16.1857862+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 38349d73-29d3-461e-b442-60fdc839faba -2024-12-20T12:10:16.2363265+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 32929f0d-ced0-4380-b7a0-31b750657f35 -2024-12-20T12:10:16.2868507+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 88bad4d3-d056-4c68-8a32-a867f1645546 -2024-12-20T12:10:16.3372484+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech b5a822b7-4b22-48b0-94ec-315c1675fe95 -2024-12-20T12:10:16.3879201+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech ccff7024-13cf-492a-adaf-3f613475083b -2024-12-20T12:10:16.4403136+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 70507dd8-3a95-458a-a496-64759b02014b -2024-12-20T12:10:16.4941057+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 7ec175e5-9ada-4de9-85f2-3cb5c3357596 -2024-12-20T12:10:16.5516327+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech bd933b4b-17e3-4f92-9e76-8f00995e2e67 -2024-12-20T12:10:16.6219546+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 55d986bb-e016-40f4-8b9f-eb4e78c2b2d2 -2024-12-20T12:10:16.7177681+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 735f3f44-8eba-4514-a535-751695161c4e -2024-12-20T12:10:16.8273002+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 6eb74488-bc4e-4996-ba00-a4d220a0d21c -2024-12-20T12:10:16.9095239+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech a697ced9-36f1-4a42-baea-3b99a97ad926 -2024-12-20T12:10:16.9648913+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 6ac7f911-58a2-4503-a48a-b76209a556a0 -2024-12-20T12:10:17.0197842+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech bb3cd2a8-522a-476e-aac8-b0af46fa6876 -2024-12-20T12:10:17.0693122+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech dfee24eb-015f-45a9-8fa3-185897c4a291 -2024-12-20T12:10:17.1007153+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech adbe9cd1-82f6-4050-bbbc-d694827c2edb -2024-12-20T12:10:17.1409954+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech fe2f41db-4c59-46ea-a315-02d0befaba4d -2024-12-20T12:10:17.1761242+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 0bf98788-d3a5-4bb0-9ed2-cf82beb91dda -2024-12-20T12:10:17.2121833+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 4e5ba332-5eb2-4fa9-a5e1-54fd17fe609b -2024-12-20T12:10:17.2448289+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 25d47168-97ba-486b-9691-aec173502574 -2024-12-20T12:10:17.2807779+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 3e2f9335-3a22-4b10-a88a-fa0ffcf14658 -2024-12-20T12:10:17.3155832+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 54712931-442f-42d5-8634-f12bd2e310ce -2024-12-20T12:10:17.3543382+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 384301e9-0e1e-4f8a-bb02-9a6a605a53ab -2024-12-20T12:10:17.3898523+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 9dee7389-af49-454c-92e4-34eaf7e86bbd -2024-12-20T12:10:17.4201259+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 5a0b613e-d585-4c12-86c3-e5ec1c974685 -2024-12-20T12:10:17.4599202+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech 9307f40f-a1d2-4419-953b-0122594c08f4 -2024-12-20T12:10:17.5099639+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported part of speech ee4114e5-98f2-4469-a6cf-42b11c8480aa -2024-12-20T12:10:17.6287390+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported complex form type 1f6ae209-141a-40db-983c-bee93af0ca3c -2024-12-20T12:10:17.6472459+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported complex form type 98c273c4-f723-4fb0-80df-eede2204dfca -2024-12-20T12:10:17.6626231+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported complex form type b2276dec-b1a6-4d82-b121-fd114c009c59 -2024-12-20T12:10:17.6799273+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported complex form type cce519d8-a9c5-4f28-9c7d-5370788bfbd5 -2024-12-20T12:10:17.6947555+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported complex form type 35cee792-74c8-444e-a9b7-ed0461d4d3b7 -2024-12-20T12:10:17.7155226+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported complex form type 9466d126-246e-400b-8bba-0703e09bc567 -2024-12-20T12:10:17.7310839+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported complex form type 73266a3a-48e8-4bd7-8c84-91c730340b7d -2024-12-20T12:10:17.7507548+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported complex form type fec038ed-6a8c-4fa5-bc96-a4f515a98c50 -2024-12-20T12:10:17.7601252+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Importing semantic domains -2024-12-20T12:10:19.4908264+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Importing 7335 entries -2024-12-20T12:11:00.9268550+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Imported 7335 entries -2024-12-20T12:11:00.9471456+01:00 INFO [FwLiteProjectSync.MiniLcmImport] [0] Import of tke-flex----temp complete, took 59 seconds, 847 milliseconds -2024-12-20T12:19:32.1195228+01:00 INFO [FwLiteShared.Layout.SvelteLayout] [0] OnAfterRenderAsync SvelteLayout -2024-12-20T12:19:33.7780398+01:00 INFO [LinqToDB.Data.DataConnection] [0] BeforeExecute -BeginTransactionAsync(Serializable) -2024-12-20T12:19:33.7877363+01:00 INFO [LinqToDB.Data.DataConnection] [0] Query Execution Time (AfterExecute) (async): 00:00:00.0141036 - -2024-12-20T12:19:33.8933223+01:00 INFO [LinqToDB.Data.DataConnection] [0] BeforeExecute --- SQLite.MS SQLite (asynchronously) -DECLARE @WsId NVarChar(3) -- String -SET @WsId = 'tke' -DECLARE @take -- Int32 -SET @take = 1000 - -SELECT - [lw_Sense].[Id_1], - [lw_Sense].[Id], - [detail_1].[Id], - [detail_1].[Sentence], - [detail_1].[Translation], - [detail_1].[Reference], - [detail_1].[SenseId], - [detail_1].[DeletedAt] -FROM - ( - SELECT DISTINCT - [detail].[Id], - [lw_Entry].[Id] as [Id_1] - FROM - ( - SELECT DISTINCT - [t2].[Id] - FROM - ( - SELECT - [t1].[Id] - FROM - [Entry] [t1] - ORDER BY - Trim(CASE - WHEN ([t1].[CitationForm]->>@WsId IS NULL OR Length([t1].[CitationForm]->>@WsId) = 0) - THEN [t1].[LexemeForm]->>@WsId - ELSE [t1].[CitationForm]->>@WsId - END) COLLATE NOCASE_WS_tke, - [t1].[Id] - LIMIT @take - ) [t2] - ) [lw_Entry] - INNER JOIN [Sense] [detail] ON [lw_Entry].[Id] = [detail].[EntryId] - ) [lw_Sense] - INNER JOIN [ExampleSentence] [detail_1] ON [lw_Sense].[Id] = [detail_1].[SenseId] - -2024-12-20T12:19:33.9353581+01:00 INFO [LinqToDB.Data.DataConnection] [0] Query Execution Time (AfterExecute) (async): 00:00:00.0457526 - -2024-12-20T12:19:34.0058432+01:00 INFO [LinqToDB.Data.DataConnection] [0] Total Execution Time (Completed) (async): 00:00:00.2069418. Rows Count: 114. - -2024-12-20T12:19:34.0081623+01:00 INFO [LinqToDB.Data.DataConnection] [0] BeforeExecute --- SQLite.MS SQLite (asynchronously) -DECLARE @WsId NVarChar(3) -- String -SET @WsId = 'tke' -DECLARE @take -- Int32 -SET @take = 1000 - -SELECT - [lw_Entry].[Id], - [detail].[Id], - [detail].[Order], - [detail].[DeletedAt], - [detail].[EntryId], - [detail].[Definition], - [detail].[Gloss], - [detail].[PartOfSpeech], - [detail].[PartOfSpeechId], - [detail].[SemanticDomains] -FROM - ( - SELECT DISTINCT - [t2].[Id] - FROM - ( - SELECT - [t1].[Id] - FROM - [Entry] [t1] - ORDER BY - Trim(CASE - WHEN ([t1].[CitationForm]->>@WsId IS NULL OR Length([t1].[CitationForm]->>@WsId) = 0) - THEN [t1].[LexemeForm]->>@WsId - ELSE [t1].[CitationForm]->>@WsId - END) COLLATE NOCASE_WS_tke, - [t1].[Id] - LIMIT @take - ) [t2] - ) [lw_Entry] - INNER JOIN [Sense] [detail] ON [lw_Entry].[Id] = [detail].[EntryId] - -2024-12-20T12:19:34.0385908+01:00 INFO [LinqToDB.Data.DataConnection] [0] Query Execution Time (AfterExecute) (async): 00:00:00.0305106 - -2024-12-20T12:19:34.1654444+01:00 INFO [LinqToDB.Data.DataConnection] [0] Total Execution Time (Completed) (async): 00:00:00.1586635. Rows Count: 1259. - -2024-12-20T12:19:34.1665343+01:00 INFO [LinqToDB.Data.DataConnection] [0] BeforeExecute --- SQLite.MS SQLite (asynchronously) -DECLARE @WsId NVarChar(3) -- String -SET @WsId = 'tke' -DECLARE @take -- Int32 -SET @take = 1000 - -SELECT - [lw_Entry].[Id], - [detail].[Id], - [detail].[DeletedAt], - [detail].[ComplexFormEntryId], - [detail].[ComplexFormHeadword], - [detail].[ComponentEntryId], - [detail].[ComponentSenseId], - [detail].[ComponentHeadword] -FROM - ( - SELECT DISTINCT - [t2].[Id] - FROM - ( - SELECT - [t1].[Id] - FROM - [Entry] [t1] - ORDER BY - Trim(CASE - WHEN ([t1].[CitationForm]->>@WsId IS NULL OR Length([t1].[CitationForm]->>@WsId) = 0) - THEN [t1].[LexemeForm]->>@WsId - ELSE [t1].[CitationForm]->>@WsId - END) COLLATE NOCASE_WS_tke, - [t1].[Id] - LIMIT @take - ) [t2] - ) [lw_Entry] - INNER JOIN [ComplexFormComponents] [detail] ON [lw_Entry].[Id] = [detail].[ComponentEntryId] - -2024-12-20T12:19:34.1951076+01:00 INFO [LinqToDB.Data.DataConnection] [0] Query Execution Time (AfterExecute) (async): 00:00:00.0286032 - -2024-12-20T12:19:34.2032156+01:00 INFO [LinqToDB.Data.DataConnection] [0] Total Execution Time (Completed) (async): 00:00:00.0372020. Rows Count: 31. - -2024-12-20T12:19:34.2052637+01:00 INFO [LinqToDB.Data.DataConnection] [0] BeforeExecute --- SQLite.MS SQLite (asynchronously) -DECLARE @WsId NVarChar(3) -- String -SET @WsId = 'tke' -DECLARE @take -- Int32 -SET @take = 1000 - -SELECT - [lw_Entry].[Id], - [detail].[Id], - [detail].[DeletedAt], - [detail].[ComplexFormEntryId], - [detail].[ComplexFormHeadword], - [detail].[ComponentEntryId], - [detail].[ComponentSenseId], - [detail].[ComponentHeadword] -FROM - ( - SELECT DISTINCT - [t2].[Id] - FROM - ( - SELECT - [t1].[Id] - FROM - [Entry] [t1] - ORDER BY - Trim(CASE - WHEN ([t1].[CitationForm]->>@WsId IS NULL OR Length([t1].[CitationForm]->>@WsId) = 0) - THEN [t1].[LexemeForm]->>@WsId - ELSE [t1].[CitationForm]->>@WsId - END) COLLATE NOCASE_WS_tke, - [t1].[Id] - LIMIT @take - ) [t2] - ) [lw_Entry] - INNER JOIN [ComplexFormComponents] [detail] ON [lw_Entry].[Id] = [detail].[ComplexFormEntryId] - -2024-12-20T12:19:34.2378022+01:00 INFO [LinqToDB.Data.DataConnection] [0] Query Execution Time (AfterExecute) (async): 00:00:00.0325789 - -2024-12-20T12:19:34.2410646+01:00 INFO [LinqToDB.Data.DataConnection] [0] Total Execution Time (Completed) (async): 00:00:00.0376711. Rows Count: 32. - -2024-12-20T12:19:34.2450010+01:00 INFO [LinqToDB.Data.DataConnection] [0] BeforeExecute --- SQLite.MS SQLite (asynchronously) -DECLARE @WsId NVarChar(3) -- String -SET @WsId = 'tke' -DECLARE @take -- Int32 -SET @take = 1000 - -SELECT - [t1].[Id], - [t1].[DeletedAt], - [t1].[LexemeForm], - [t1].[CitationForm], - [t1].[LiteralMeaning], - [t1].[Note], - [t1].[ComplexFormTypes] -FROM - [Entry] [t1] -ORDER BY - Trim(CASE - WHEN ([t1].[CitationForm]->>@WsId IS NULL OR Length([t1].[CitationForm]->>@WsId) = 0) - THEN [t1].[LexemeForm]->>@WsId - ELSE [t1].[CitationForm]->>@WsId - END) COLLATE NOCASE_WS_tke, - [t1].[Id] -LIMIT @take - -2024-12-20T12:19:34.2701536+01:00 INFO [LinqToDB.Data.DataConnection] [0] Query Execution Time (AfterExecute) (async): 00:00:00.0251852 - -2024-12-20T12:19:34.2935785+01:00 INFO [LinqToDB.Data.DataConnection] [0] Total Execution Time (Completed) (async): 00:00:00.0491019. Rows Count: 1000. - -2024-12-20T12:19:34.2953410+01:00 INFO [LinqToDB.Data.DataConnection] [0] BeforeExecute -DisposeTransactionAsync -2024-12-20T12:19:34.2961644+01:00 INFO [LinqToDB.Data.DataConnection] [0] Query Execution Time (AfterExecute) (async): 00:00:00.0008210 - -2024-12-20T12:19:34.6240946+01:00 INFO [LinqToDB.Data.DataConnection] [0] BeforeExecute -BeginTransactionAsync(Serializable) -2024-12-20T12:19:34.6243646+01:00 INFO [LinqToDB.Data.DataConnection] [0] Query Execution Time (AfterExecute) (async): 00:00:00.0002761 - -2024-12-20T12:19:34.6250515+01:00 INFO [LinqToDB.Data.DataConnection] [0] BeforeExecute --- SQLite.MS SQLite (asynchronously) -DECLARE @id -- Guid -SET @id = '1C5C77B7-7423-4E13-9F0C-DA22412FD99F' -DECLARE @take -- Int32 -SET @take = 1 - -SELECT - [lw_Sense].[Id_1], - [lw_Sense].[Id], - [detail_1].[Id], - [detail_1].[Sentence], - [detail_1].[Translation], - [detail_1].[Reference], - [detail_1].[SenseId], - [detail_1].[DeletedAt] -FROM - ( - SELECT DISTINCT - [detail].[Id], - [lw_Entry].[Id] as [Id_1] - FROM - ( - SELECT DISTINCT - [t1].[Id] - FROM - ( - SELECT - [e].[Id] - FROM - [Entry] [e] - WHERE - [e].[Id] = @id - LIMIT @take - ) [t1] - ) [lw_Entry] - INNER JOIN [Sense] [detail] ON [lw_Entry].[Id] = [detail].[EntryId] - ) [lw_Sense] - INNER JOIN [ExampleSentence] [detail_1] ON [lw_Sense].[Id] = [detail_1].[SenseId] - -2024-12-20T12:19:34.6252907+01:00 INFO [LinqToDB.Data.DataConnection] [0] Query Execution Time (AfterExecute) (async): 00:00:00.0003022 - -2024-12-20T12:19:34.6253723+01:00 INFO [LinqToDB.Data.DataConnection] [0] Total Execution Time (Completed) (async): 00:00:00.0009290. Rows Count: 0. - -2024-12-20T12:19:34.6256305+01:00 INFO [LinqToDB.Data.DataConnection] [0] BeforeExecute --- SQLite.MS SQLite (asynchronously) -DECLARE @id -- Guid -SET @id = '1C5C77B7-7423-4E13-9F0C-DA22412FD99F' -DECLARE @take -- Int32 -SET @take = 1 - -SELECT - [lw_Entry].[Id], - [detail].[Id], - [detail].[Order], - [detail].[DeletedAt], - [detail].[EntryId], - [detail].[Definition], - [detail].[Gloss], - [detail].[PartOfSpeech], - [detail].[PartOfSpeechId], - [detail].[SemanticDomains] -FROM - ( - SELECT DISTINCT - [t1].[Id] - FROM - ( - SELECT - [e].[Id] - FROM - [Entry] [e] - WHERE - [e].[Id] = @id - LIMIT @take - ) [t1] - ) [lw_Entry] - INNER JOIN [Sense] [detail] ON [lw_Entry].[Id] = [detail].[EntryId] - -2024-12-20T12:19:34.6257457+01:00 INFO [LinqToDB.Data.DataConnection] [0] Query Execution Time (AfterExecute) (async): 00:00:00.0001418 - -2024-12-20T12:19:34.6306901+01:00 INFO [LinqToDB.Data.DataConnection] [0] Total Execution Time (Completed) (async): 00:00:00.0052146. Rows Count: 1. - -2024-12-20T12:19:34.6312479+01:00 INFO [LinqToDB.Data.DataConnection] [0] BeforeExecute --- SQLite.MS SQLite (asynchronously) -DECLARE @id -- Guid -SET @id = '1C5C77B7-7423-4E13-9F0C-DA22412FD99F' -DECLARE @take -- Int32 -SET @take = 1 - -SELECT - [lw_Entry].[Id], - [detail].[Id], - [detail].[DeletedAt], - [detail].[ComplexFormEntryId], - [detail].[ComplexFormHeadword], - [detail].[ComponentEntryId], - [detail].[ComponentSenseId], - [detail].[ComponentHeadword] -FROM - ( - SELECT DISTINCT - [t1].[Id] - FROM - ( - SELECT - [e].[Id] - FROM - [Entry] [e] - WHERE - [e].[Id] = @id - LIMIT @take - ) [t1] - ) [lw_Entry] - INNER JOIN [ComplexFormComponents] [detail] ON [lw_Entry].[Id] = [detail].[ComponentEntryId] - -2024-12-20T12:19:34.6314269+01:00 INFO [LinqToDB.Data.DataConnection] [0] Query Execution Time (AfterExecute) (async): 00:00:00.0002567 - -2024-12-20T12:19:34.6314706+01:00 INFO [LinqToDB.Data.DataConnection] [0] Total Execution Time (Completed) (async): 00:00:00.0007173. Rows Count: 0. - -2024-12-20T12:19:34.6318438+01:00 INFO [LinqToDB.Data.DataConnection] [0] BeforeExecute --- SQLite.MS SQLite (asynchronously) -DECLARE @id -- Guid -SET @id = '1C5C77B7-7423-4E13-9F0C-DA22412FD99F' -DECLARE @take -- Int32 -SET @take = 1 - -SELECT - [lw_Entry].[Id], - [detail].[Id], - [detail].[DeletedAt], - [detail].[ComplexFormEntryId], - [detail].[ComplexFormHeadword], - [detail].[ComponentEntryId], - [detail].[ComponentSenseId], - [detail].[ComponentHeadword] -FROM - ( - SELECT DISTINCT - [t1].[Id] - FROM - ( - SELECT - [e].[Id] - FROM - [Entry] [e] - WHERE - [e].[Id] = @id - LIMIT @take - ) [t1] - ) [lw_Entry] - INNER JOIN [ComplexFormComponents] [detail] ON [lw_Entry].[Id] = [detail].[ComplexFormEntryId] - -2024-12-20T12:19:34.6320161+01:00 INFO [LinqToDB.Data.DataConnection] [0] Query Execution Time (AfterExecute) (async): 00:00:00.0002084 - -2024-12-20T12:19:34.6320602+01:00 INFO [LinqToDB.Data.DataConnection] [0] Total Execution Time (Completed) (async): 00:00:00.0005650. Rows Count: 0. - -2024-12-20T12:19:34.6394237+01:00 INFO [LinqToDB.Data.DataConnection] [0] BeforeExecute --- SQLite.MS SQLite (asynchronously) -DECLARE @id -- Guid -SET @id = '1C5C77B7-7423-4E13-9F0C-DA22412FD99F' -DECLARE @take -- Int32 -SET @take = 2 - -SELECT - [e].[Id], - [e].[DeletedAt], - [e].[LexemeForm], - [e].[CitationForm], - [e].[LiteralMeaning], - [e].[Note], - [e].[ComplexFormTypes] -FROM - [Entry] [e] -WHERE - [e].[Id] = @id -LIMIT @take - -2024-12-20T12:19:34.6396915+01:00 INFO [LinqToDB.Data.DataConnection] [0] Query Execution Time (AfterExecute) (async): 00:00:00.0003597 - -2024-12-20T12:19:34.6477603+01:00 INFO [LinqToDB.Data.DataConnection] [0] Total Execution Time (Completed) (async): 00:00:00.0088798. Rows Count: 1. - -2024-12-20T12:19:34.6479092+01:00 INFO [LinqToDB.Data.DataConnection] [0] BeforeExecute -DisposeTransactionAsync -2024-12-20T12:19:34.6480837+01:00 INFO [LinqToDB.Data.DataConnection] [0] Query Execution Time (AfterExecute) (async): 00:00:00.0001649 - -2024-12-20T12:19:34.8631283+01:00 WARN [FwLiteShared.Sync.SyncService] [0] Project tke-flex----temp has no origin domain, unable to create http sync client -2024-12-20T12:19:49.5432120+01:00 INFO [Microsoft.Maui.Hosting.MauiApp] [0] Disposing app -2024-12-20T12:19:49.5480101+01:00 INFO [FwDataMiniLcmBridge.FwDataFactory] [0] Closing all projects -2024-12-20T12:19:49.5476182+01:00 FAIL [Microsoft.Maui.Hosting.MauiApp] [0] Unhandled exceptionSystem.ObjectDisposedException: Cannot access a disposed object. -Object name: 'IServiceProvider'. - at Microsoft.Extensions.DependencyInjection.ServiceLookup.ThrowHelper.ThrowObjectDisposedException() - at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(ServiceIdentifier serviceIdentifier, ServiceProviderEngineScope serviceProviderEngineScope) - at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType) - at Microsoft.Maui.MauiContext.WrappedServiceProvider.GetService(Type serviceType) - at Microsoft.Maui.LifecycleEvents.LifecycleEventServiceExtensions.GetLifecycleEventDelegates[TDelegate](IServiceProvider services, String eventName)+MoveNext() - at Microsoft.Maui.LifecycleEvents.LifecycleEventServiceExtensions.InvokeLifecycleEvents[TDelegate](IServiceProvider services, Action`1 action) - at Microsoft.Maui.MauiWinUIWindow.g__OnWindowMessage|14_1(Object sender, WindowMessageEventArgs e) - at Microsoft.Maui.ApplicationModel.WindowMessageManager.NewWindowProc(IntPtr hWnd, UInt32 uMsg, IntPtr wParam, IntPtr lParam) - diff --git a/backend/FwLite/FwLiteShared/FwLiteConfig.cs b/backend/FwLite/FwLiteShared/FwLiteConfig.cs new file mode 100644 index 000000000..880cd4d74 --- /dev/null +++ b/backend/FwLite/FwLiteShared/FwLiteConfig.cs @@ -0,0 +1,28 @@ +using System.Runtime.InteropServices; + +namespace FwLiteShared; + +public class FwLiteConfig +{ + public bool UseDevAssets { get; set; } = false; + public string AppVersion { get; set; } = "Unknown"; + public FwLitePlatform Os { get; set; } = Environment.OSVersion.Platform switch { + PlatformID.Win32NT => FwLitePlatform.Windows, + PlatformID.Unix => FwLitePlatform.Linux, + PlatformID.MacOSX => FwLitePlatform.Mac, + _ => FwLitePlatform.Other + }; + public string FeedbackUrl => $"https://docs.google.com/forms/d/e/1FAIpQLSdUdNufT3sdoBscY7vixguYnvtgpaw-hjX-z54BKi9KlYv4vw/viewform?usp=pp_url&entry.2102942583={AppVersion}&entry.1772086822={Os}"; +} + +public enum FwLitePlatform +{ + Windows, + Linux, + Mac, + Other, + Android, + // ReSharper disable once InconsistentNaming + iOS, + Web +} diff --git a/backend/FwLite/FwLiteShared/FwLiteSharedKernel.cs b/backend/FwLite/FwLiteShared/FwLiteSharedKernel.cs index ef7fe8eec..9c0af4153 100644 --- a/backend/FwLite/FwLiteShared/FwLiteSharedKernel.cs +++ b/backend/FwLite/FwLiteShared/FwLiteSharedKernel.cs @@ -25,6 +25,7 @@ public static IServiceCollection AddFwLiteShared(this IServiceCollection service services.AddSingleton(); services.AddSingleton(); services.AddSingleton(s => s.GetRequiredService()); + services.AddOptions(); return services; } diff --git a/backend/FwLite/FwLiteShared/Layout/SvelteLayout.razor b/backend/FwLite/FwLiteShared/Layout/SvelteLayout.razor index 6b35a9ab6..5f0f58fde 100644 --- a/backend/FwLite/FwLiteShared/Layout/SvelteLayout.razor +++ b/backend/FwLite/FwLiteShared/Layout/SvelteLayout.razor @@ -2,10 +2,11 @@ @using FwLiteShared.Services @using Microsoft.Extensions.Hosting @using Microsoft.Extensions.Logging +@using Microsoft.Extensions.Options @inject IJSRuntime JS @inject ILogger Logger @inject FwLiteProvider FwLiteProvider -@inject IHostEnvironment Environment; +@inject IOptions Config; @implements IAsyncDisposable @if (useDevAssets) { @@ -44,7 +45,7 @@ else @Body @code { - private bool useDevAssets => Environment.IsDevelopment(); + private bool useDevAssets => Config.Value.UseDevAssets; // private bool useDevAssets => false; private IJSObjectReference? module; diff --git a/backend/FwLite/FwLiteShared/Services/FwLiteProvider.cs b/backend/FwLite/FwLiteShared/Services/FwLiteProvider.cs index cfd2ad81a..f862d15bb 100644 --- a/backend/FwLite/FwLiteShared/Services/FwLiteProvider.cs +++ b/backend/FwLite/FwLiteShared/Services/FwLiteProvider.cs @@ -6,6 +6,7 @@ using LexCore.Utils; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Microsoft.JSInterop; using MiniLcm.Models; using MiniLcm.Project; @@ -20,7 +21,8 @@ public class FwLiteProvider( LexboxProjectService lexboxProjectService, ChangeEventBus changeEventBus, IEnumerable projectProviders, - ILogger logger + ILogger logger, + IOptions config ) : IDisposable { public const string OverrideServiceFunctionName = "setOverrideService"; @@ -50,6 +52,7 @@ public object GetService(DotnetService service) DotnetService.CombinedProjectsService => projectService, DotnetService.AuthService => authService, DotnetService.ImportFwdataService => importFwdataService, + DotnetService.FwLiteConfig => config.Value, _ => throw new ArgumentOutOfRangeException(nameof(service), service, null) }; } @@ -57,19 +60,30 @@ public object GetService(DotnetService service) public async Task SetService(IJSRuntime jsRuntime, DotnetService service, object? serviceInstance) { DotNetObjectReference? reference = null; - if (serviceInstance is not null) + if (serviceInstance is null) { - reference = DotNetObjectReference.Create(serviceInstance); + logger.LogInformation("Clearing Service {Service}", service); } - else + if (ShouldConvertToDotnetObject(service, serviceInstance)) { - logger.LogInformation("Clearing Service {Service}", service); + reference = DotNetObjectReference.Create(serviceInstance); + serviceInstance = reference; } - await jsRuntime.DurableInvokeVoidAsync(OverrideServiceFunctionName, service.ToString(), reference); + await jsRuntime.DurableInvokeVoidAsync(OverrideServiceFunctionName, service.ToString(), serviceInstance); return reference; } + + private bool ShouldConvertToDotnetObject(DotnetService service, [NotNullWhen(true)] object? serviceInstance) + { + return serviceInstance is not null && service switch + { + DotnetService.FwLiteConfig => false, + _ => true + }; + } + public async Task InjectCrdtProject(IJSRuntime jsRuntime, IServiceProvider scopedServices, string projectName) @@ -114,4 +128,5 @@ public enum DotnetService CombinedProjectsService, AuthService, ImportFwdataService, + FwLiteConfig, } diff --git a/backend/FwLite/FwLiteShared/Services/VersionHelper.cs b/backend/FwLite/FwLiteShared/Services/VersionHelper.cs new file mode 100644 index 000000000..ae3307aa8 --- /dev/null +++ b/backend/FwLite/FwLiteShared/Services/VersionHelper.cs @@ -0,0 +1,18 @@ +using System.Reflection; + +namespace FwLiteShared.Services; + +public class VersionHelper +{ + public static string DisplayVersion(Assembly assembly) + { + var infoVersion = assembly.GetCustomAttribute()?.InformationalVersion; + //info version may look like v2024-12-12-3073dd1c+3073dd1ce2ff5510f54a9411366f55c958b9ea45. We want to strip off everything after the +, so we can compare versions + if (infoVersion is not null && infoVersion.Contains('+')) + { + infoVersion = infoVersion[..infoVersion.IndexOf('+')]; + } + + return infoVersion ?? "dev"; + } +} diff --git a/backend/FwLite/FwLiteShared/TypeGen/ReinforcedFwLiteTypingConfig.cs b/backend/FwLite/FwLiteShared/TypeGen/ReinforcedFwLiteTypingConfig.cs index 13e805cd4..f7962ebda 100644 --- a/backend/FwLite/FwLiteShared/TypeGen/ReinforcedFwLiteTypingConfig.cs +++ b/backend/FwLite/FwLiteShared/TypeGen/ReinforcedFwLiteTypingConfig.cs @@ -77,6 +77,8 @@ public static void Configure(ConfigurationBuilder builder) builder.ExportAsInterface().WithPublicProperties(); builder.ExportAsInterface().WithPublicProperties(); builder.ExportAsInterface().WithPublicProperties(); + builder.ExportAsInterface().WithPublicProperties(); + builder.ExportAsEnum().UseString(); builder.ExportAsEnum(); } diff --git a/backend/FwLite/FwLiteWeb/FwLiteWebKernel.cs b/backend/FwLite/FwLiteWeb/FwLiteWebKernel.cs index 27b957e92..133c36a3c 100644 --- a/backend/FwLite/FwLiteWeb/FwLiteWebKernel.cs +++ b/backend/FwLite/FwLiteWeb/FwLiteWebKernel.cs @@ -1,4 +1,6 @@ -using SIL.Harmony; +using FwDataMiniLcmBridge; +using FwLiteProjectSync; +using SIL.Harmony; using FwLiteShared; using FwLiteShared.Auth; using LcmCrdt; @@ -16,7 +18,13 @@ public static IServiceCollection AddFwLiteWebServices(this IServiceCollection se services.AddHttpContextAccessor(); services.AddSingleton(); services.AddSingleton(); + services.AddFwDataBridge(); + services.AddFwLiteProjectSync(); services.AddFwLiteShared(environment); + if (environment.IsDevelopment()) + { + services.Configure(config => config.UseDevAssets = true); + } services.AddOptions().BindConfiguration("FwLiteWeb"); diff --git a/backend/FwLite/FwLiteWeb/FwLiteWebServer.cs b/backend/FwLite/FwLiteWeb/FwLiteWebServer.cs index 34ae69475..1d73fbf24 100644 --- a/backend/FwLite/FwLiteWeb/FwLiteWebServer.cs +++ b/backend/FwLite/FwLiteWeb/FwLiteWebServer.cs @@ -1,6 +1,8 @@ using FwDataMiniLcmBridge; using FwDataMiniLcmBridge.LcmUtils; +using FwLiteShared; using FwLiteShared.Auth; +using FwLiteShared.Services; using LcmCrdt; using FwLiteWeb; using FwLiteWeb.Components; @@ -36,7 +38,11 @@ public static WebApplication SetupAppServer(WebApplicationOptions options, Actio ]); builder.ConfigureProd(config => config.LexboxServers = [new(new("https://staging.languagedepot.org"), "Lexbox Staging")]); - builder.Services.Configure(c => c.ClientId = "becf2856-0690-434b-b192-a4032b72067f"); + builder.Services.Configure(config => + { + config.AppVersion = VersionHelper.DisplayVersion(typeof(FwLiteWebServer).Assembly); + //todo os should be web, when the server is running remotely to the client, but linux runs the server locally so we will default using the OS to determine the platform (the default value) + }); builder.Logging.AddDebug(); builder.Services.AddRazorComponents().AddInteractiveServerComponents(circuitOptions => circuitOptions.DetailedErrors = true); if (builder.Configuration.GetValue("FwLiteWeb:LogFileName") is { Length: > 0 } logFileName) diff --git a/frontend/viewer/src/App.svelte b/frontend/viewer/src/App.svelte index 42694a135..f0aefe038 100644 --- a/frontend/viewer/src/App.svelte +++ b/frontend/viewer/src/App.svelte @@ -13,7 +13,6 @@ - -
- -
- - - - -
-
-
-
-
-
My projects
- -
- {#await projectsPromise} -

loading...

- {:then projects} - p.fwdata || p.crdt).sort((p1, p2) => p1.name.localeCompare(p2.name))} - classes={{ th: 'p-4' }}> - - {#each data ?? [] as project, rowIndex} - - {#each columns as column (column.name)} - - {/each} - - {/each} - - - - - - - - -
- {#if column.name === 'fwdata'} - {#if project.fwdata} - - {/if} - {:else if column.name === 'lexbox'} - {@const server = syncedServer(remoteProjects, project)} - {#if project.crdt && server} - - {/if} - {:else if column.name === 'crdt'} - {#if project.crdt} - - {:else if project.fwdata} - - {/if} - {:else} - {getCellContent(column, project, rowIndex)} - {/if} -
- Test project - - -
- {:catch error} -

Error: {error.message}

- {/await} -
-
Remote projects - {#if loadingRemoteProjects} - + +
+ + + + Lexbox logo + +

Projects

+
+
+ +
+
+
+ +
+ {#await projectsPromise} +

loading...

+ {:then projects} +
+
+

Local

+
+ {#each projects.filter(p => p.crdt) as project, i (project.id ?? i)} + {@const server = syncedServer(remoteProjects, project, serversStatus)} + + +
+
+
+
+ {/each} + + +
+
+
+
+ {#if !projects.some(p => p.name === exampleProjectName) || $isDev} + createProject(exampleProjectName)}> +
+
+
+ {/if} +
+
+ {#each serversStatus as status} + {@const server = status.server} + {@const serverProjects = remoteProjects[server.authority]?.filter(p => p.crdt) ?? []} +
+
+

{server.displayName} Server

+
+ {#if status.loggedIn} + refreshProjectsAndServers()}/> {/if}
- {#each serversStatus as status} - {@const server = status.server} -
-
-

{server.displayName}

-
- {#if status.loggedInAs} -

{status.loggedInAs}

- {/if} - refreshProjectsAndServers()} /> -
- {@const serverProjects = remoteProjects[server.authority]?.filter(p => p.crdt) ?? []} +
+ {#if !serverProjects.length} +

+ {#if status.loggedIn} + No projects + {:else} + refreshProjectsAndServers()}/> + {/if} +

+ {/if} {#each serverProjects as project} {@const localProject = matchesProject(projects, project)} -
-

{project.name}

-
- {#if localProject?.crdt} - - {:else} - - {/if} -
+
+ {/each} - {/each} +
-
- -
-
+ {/each} + + {#if projects.some(p => p.fwdata)} +
+

Legacy FieldWorks Projects

+
+ {#each projects.filter(p => p.fwdata) as project (project.id ?? project.name)} + + + FieldWorks logo +
+ + + +
+
+
+ {/each} +
+
+ {/if} +
+ {:catch error} +

Error: {error.message}

+ {/await}
+ +
diff --git a/frontend/viewer/src/ProjectView.svelte b/frontend/viewer/src/ProjectView.svelte index db4ec645a..af05d74b9 100644 --- a/frontend/viewer/src/ProjectView.svelte +++ b/frontend/viewer/src/ProjectView.svelte @@ -11,7 +11,7 @@ import Editor from './lib/Editor.svelte'; import {navigate, useLocation} from 'svelte-routing'; import {headword} from './lib/utils'; - import {useLexboxApi} from './lib/services/service-provider'; + import {useFwLiteConfig, useLexboxApi} from './lib/services/service-provider'; import type {IEntry} from './lib/dotnet-types'; import {onDestroy, onMount, setContext} from 'svelte'; import {derived, type Readable, writable} from 'svelte/store'; @@ -65,6 +65,7 @@ }); })); + const fwLiteConfig = useFwLiteConfig(); const lexboxApi = useLexboxApi(); void lexboxApi.supportedFeatures().then(f => { features.set(f); @@ -345,7 +346,7 @@ {/if} {#if $features.feedback} +{#if status.loggedIn} + + + {:else} {#if $shouldUseSystemWebView} {:else} {/if} {/if} diff --git a/frontend/viewer/src/lib/dotnet-types/generated-types/FwLiteShared/FwLitePlatform.ts b/frontend/viewer/src/lib/dotnet-types/generated-types/FwLiteShared/FwLitePlatform.ts new file mode 100644 index 000000000..20152bd06 --- /dev/null +++ b/frontend/viewer/src/lib/dotnet-types/generated-types/FwLiteShared/FwLitePlatform.ts @@ -0,0 +1,15 @@ +/* eslint-disable */ +// This code was generated by a Reinforced.Typings tool. +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. + +export enum FwLitePlatform { + Windows = "Windows", + Linux = "Linux", + Mac = "Mac", + Other = "Other", + Android = "Android", + iOS = "iOS", + Web = "Web" +} +/* eslint-enable */ diff --git a/frontend/viewer/src/lib/dotnet-types/generated-types/FwLiteShared/IFwLiteConfig.ts b/frontend/viewer/src/lib/dotnet-types/generated-types/FwLiteShared/IFwLiteConfig.ts new file mode 100644 index 000000000..6dad532af --- /dev/null +++ b/frontend/viewer/src/lib/dotnet-types/generated-types/FwLiteShared/IFwLiteConfig.ts @@ -0,0 +1,15 @@ +/* eslint-disable */ +// This code was generated by a Reinforced.Typings tool. +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. + +import type {FwLitePlatform} from './FwLitePlatform'; + +export interface IFwLiteConfig +{ + useDevAssets: boolean; + appVersion: string; + os: FwLitePlatform; + feedbackUrl: string; +} +/* eslint-enable */ diff --git a/frontend/viewer/src/lib/dotnet-types/generated-types/FwLiteShared/Services/DotnetService.ts b/frontend/viewer/src/lib/dotnet-types/generated-types/FwLiteShared/Services/DotnetService.ts index 4edb057a7..14d613cae 100644 --- a/frontend/viewer/src/lib/dotnet-types/generated-types/FwLiteShared/Services/DotnetService.ts +++ b/frontend/viewer/src/lib/dotnet-types/generated-types/FwLiteShared/Services/DotnetService.ts @@ -7,6 +7,7 @@ export enum DotnetService { MiniLcmApi = "MiniLcmApi", CombinedProjectsService = "CombinedProjectsService", AuthService = "AuthService", - ImportFwdataService = "ImportFwdataService" + ImportFwdataService = "ImportFwdataService", + FwLiteConfig = "FwLiteConfig" } /* eslint-enable */ diff --git a/frontend/viewer/src/lib/entry-editor/DeleteDialog.svelte b/frontend/viewer/src/lib/entry-editor/DeleteDialog.svelte index b8d450e44..881ac8e8c 100644 --- a/frontend/viewer/src/lib/entry-editor/DeleteDialog.svelte +++ b/frontend/viewer/src/lib/entry-editor/DeleteDialog.svelte @@ -33,7 +33,7 @@
Delete {subject}
-
+

Are you sure you want to delete {subject}?

diff --git a/frontend/viewer/src/lib/layout/DevContent.svelte b/frontend/viewer/src/lib/layout/DevContent.svelte index b56750d24..4ce681a65 100644 --- a/frontend/viewer/src/lib/layout/DevContent.svelte +++ b/frontend/viewer/src/lib/layout/DevContent.svelte @@ -12,6 +12,14 @@ isDev.set(localStorage.getItem('devMode') === 'true'); + + {#if $isDev} +{:else if invisible} + {/if} diff --git a/frontend/viewer/src/lib/notifications/NotificationOutlet.svelte b/frontend/viewer/src/lib/notifications/NotificationOutlet.svelte index 59d9f32e4..a7aa6c9fc 100644 --- a/frontend/viewer/src/lib/notifications/NotificationOutlet.svelte +++ b/frontend/viewer/src/lib/notifications/NotificationOutlet.svelte @@ -13,7 +13,7 @@ {#if $notifications.length}
{#each $notifications as notification} -
+
{#if notification.type === 'success'} diff --git a/frontend/viewer/src/lib/services/service-provider-dotnet.ts b/frontend/viewer/src/lib/services/service-provider-dotnet.ts index 264f4c04f..7bdafcf89 100644 --- a/frontend/viewer/src/lib/services/service-provider-dotnet.ts +++ b/frontend/viewer/src/lib/services/service-provider-dotnet.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/naming-convention */ import './service-declaration'; -import { type DotNet } from '@microsoft/dotnet-js-interop'; +import { DotNet } from '@microsoft/dotnet-js-interop'; import {type LexboxServiceRegistry, SERVICE_KEYS, type ServiceKey} from './service-provider'; export class DotNetServiceProvider { private services: LexboxServiceRegistry; @@ -19,11 +19,17 @@ export class DotNetServiceProvider { public getService(key: K): LexboxServiceRegistry[K] | undefined { this.validateAllServices(); - const service = this.services[key] as unknown as DotNet.DotNetObject; + const service = this.services[key] as LexboxServiceRegistry[K] | DotNet.DotNetObject | undefined; //todo maybe don't return undefined if (!service) return undefined; - return wrapInProxy(service) as LexboxServiceRegistry[K]; + if (this.isDotnetObject(service)) return wrapInProxy(service) as LexboxServiceRegistry[K]; + return service; } + + private isDotnetObject(service: object): service is DotNet.DotNetObject { + return service instanceof DotNet.DotNetObject || 'invokeMethodAsync' in service; + } + private validateAllServices() { const validServiceKeys = SERVICE_KEYS; for (const [key, value] of Object.entries(this.services)) { diff --git a/frontend/viewer/src/lib/services/service-provider.ts b/frontend/viewer/src/lib/services/service-provider.ts index 1f6cbf591..d0deedec4 100644 --- a/frontend/viewer/src/lib/services/service-provider.ts +++ b/frontend/viewer/src/lib/services/service-provider.ts @@ -4,6 +4,7 @@ import {DotnetService, type ICombinedProjectsService, type IAuthService} from '. import type {IImportFwdataService} from '$lib/dotnet-types/generated-types/FwLiteShared/Projects/IImportFwdataService'; import type {IMiniLcmJsInvokable} from '$lib/dotnet-types/generated-types/FwLiteShared/Services/IMiniLcmJsInvokable'; import {useEventBus} from './event-bus'; +import type {IFwLiteConfig} from '$lib/dotnet-types/generated-types/FwLiteShared/IFwLiteConfig'; export enum LexboxService { LexboxApi = 'LexboxApi' @@ -14,6 +15,7 @@ export type LexboxServiceRegistry = { [DotnetService.CombinedProjectsService]: ICombinedProjectsService, [DotnetService.AuthService]: IAuthService, [DotnetService.ImportFwdataService]: IImportFwdataService, + [DotnetService.FwLiteConfig]: IFwLiteConfig }; export const SERVICE_KEYS = [...Object.values(LexboxService), ...Object.values(DotnetService)]; @@ -63,3 +65,7 @@ export function useAuthService(): IAuthService { export function useImportFwdataService(): IImportFwdataService { return window.lexbox.ServiceProvider.getService(DotnetService.ImportFwdataService); } + +export function useFwLiteConfig(): IFwLiteConfig { + return window.lexbox.ServiceProvider.getService(DotnetService.FwLiteConfig); +} diff --git a/frontend/viewer/src/lib/utils/AnchorListItem.svelte b/frontend/viewer/src/lib/utils/AnchorListItem.svelte new file mode 100644 index 000000000..7aefc164a --- /dev/null +++ b/frontend/viewer/src/lib/utils/AnchorListItem.svelte @@ -0,0 +1,20 @@ + + + +
+ +
+
+ +