diff --git a/starsky/starsky.foundation.platform/Helpers/SetupAppSettings.cs b/starsky/starsky.foundation.platform/Helpers/SetupAppSettings.cs index 9b709af27..3a74f0f1d 100644 --- a/starsky/starsky.foundation.platform/Helpers/SetupAppSettings.cs +++ b/starsky/starsky.foundation.platform/Helpers/SetupAppSettings.cs @@ -12,113 +12,112 @@ [assembly: InternalsVisibleTo("starskytest")] -namespace starsky.foundation.platform.Helpers +namespace starsky.foundation.platform.Helpers; + +public static class SetupAppSettings { - public static class SetupAppSettings + public static async Task FirstStepToAddSingleton( + ServiceCollection services) { - public static async Task FirstStepToAddSingleton( - ServiceCollection services) - { - services.AddSingleton(new ConfigurationBuilder().Build()); - var configurationRoot = await AppSettingsToBuilder(); - services.ConfigurePoCo(configurationRoot.GetSection("App")); - return services; - } - - /// - /// Default appSettings.json to builder - /// - /// ConfigBuilder - public static async Task AppSettingsToBuilder(string[]? args = null) - { - var appSettings = new AppSettings(); - var builder = new ConfigurationBuilder(); - - var settings = await MergeJsonFiles(appSettings.BaseDirectoryProject); + services.AddSingleton(new ConfigurationBuilder().Build()); + var configurationRoot = await AppSettingsToBuilder(); + services.ConfigurePoCo(configurationRoot.GetSection("App")); + return services; + } - // Make sure is wrapped in a AppContainer app - var appContainer = new AppContainerAppSettings { App = settings }; - var utf8Bytes = JsonSerializer.SerializeToUtf8Bytes(appContainer); + /// + /// Default appSettings.json to builder + /// + /// ConfigBuilder + public static async Task AppSettingsToBuilder(string[]? args = null) + { + var appSettings = new AppSettings(); + var builder = new ConfigurationBuilder(); - builder - .AddJsonStream(new MemoryStream(utf8Bytes)) - // overwrite envs - // current dir gives problems on linux arm - .AddEnvironmentVariables(); + var settings = await MergeJsonFiles(appSettings.BaseDirectoryProject); - if ( args != null ) - { - builder.AddCommandLine(args); - } + // Make sure is wrapped in a AppContainer app + var appContainer = new AppContainerAppSettings { App = settings }; + var utf8Bytes = JsonSerializer.SerializeToUtf8Bytes(appContainer); - return builder.Build(); - } + builder + .AddJsonStream(new MemoryStream(utf8Bytes)) + // overwrite envs + // current dir gives problems on linux arm + .AddEnvironmentVariables(); - internal static string AppSettingsMachineNameWithDot() + if ( args != null ) { - // to remove spaces and other signs, check help to get your name - return $"appsettings.{Environment.MachineName.ToLowerInvariant()}."; // dot here + builder.AddCommandLine(args); } - private static IEnumerable Order(string baseDirectoryProject) - { - var appSettingsMachine = AppSettingsMachineNameWithDot(); - var appSettingsPath = - Environment.GetEnvironmentVariable("app__appsettingspath") ?? string.Empty; - return new List - { - Path.Combine(baseDirectoryProject, "appsettings.json"), - Path.Combine(baseDirectoryProject, "appsettings.default.json"), - Path.Combine(baseDirectoryProject, "appsettings.patch.json"), - Path.Combine(baseDirectoryProject, appSettingsMachine + "json"), - Path.Combine(baseDirectoryProject, appSettingsMachine + "patch.json"), - appSettingsPath - }.Where(p => !string.IsNullOrEmpty(p)); - } + return builder.Build(); + } + + internal static string AppSettingsMachineNameWithDot() + { + // to remove spaces and other signs, check help to get your name + return $"appsettings.{Environment.MachineName.ToLowerInvariant()}."; // dot here + } - internal static async Task MergeJsonFiles(string baseDirectoryProject) + private static IEnumerable Order(string baseDirectoryProject) + { + var appSettingsMachine = AppSettingsMachineNameWithDot(); + var appSettingsPath = + Environment.GetEnvironmentVariable("app__appsettingspath") ?? string.Empty; + return new List { - var paths = Order(baseDirectoryProject); - var appSettingsList = new List(); + Path.Combine(baseDirectoryProject, "appsettings.json"), + Path.Combine(baseDirectoryProject, "appsettings.default.json"), + Path.Combine(baseDirectoryProject, "appsettings.patch.json"), + Path.Combine(baseDirectoryProject, appSettingsMachine + "json"), + Path.Combine(baseDirectoryProject, appSettingsMachine + "patch.json"), + appSettingsPath + }.Where(p => !string.IsNullOrEmpty(p)); + } - foreach ( var path in paths.Where(File.Exists) ) - { - var appSettings = await ReadAppSettings.Read(path); - appSettingsList.Add(appSettings!.App); - } + internal static async Task MergeJsonFiles(string baseDirectoryProject) + { + var paths = Order(baseDirectoryProject); + var appSettingsList = new List(); - if ( appSettingsList.Count == 0 ) - { - return new AppSettings(); - } + foreach ( var path in paths.Where(File.Exists) ) + { + var appSettings = await ReadAppSettings.Read(path); + appSettingsList.Add(appSettings!.App); + } - var appSetting = appSettingsList.FirstOrDefault()!; + if ( appSettingsList.Count == 0 ) + { + return new AppSettings(); + } - for ( var i = 1; i < appSettingsList.Count; i++ ) - { - var currentAppSetting = appSettingsList[i]; - AppSettingsCompareHelper.Compare(appSetting, currentAppSetting); - } + var appSetting = appSettingsList[0]; - return appSetting; + for ( var i = 1; i < appSettingsList.Count; i++ ) + { + var currentAppSetting = appSettingsList[i]; + AppSettingsCompareHelper.Compare(appSetting, currentAppSetting); } - /// - /// Configure the PoCo the dependency injection - /// - /// services - /// - /// - public static AppSettings ConfigurePoCoAppSettings(IServiceCollection services, - IConfigurationRoot configuration) - { - // configs - services.ConfigurePoCo(configuration.GetSection("App")); + return appSetting; + } - // Need to rebuild for AppSettings - var serviceProvider = services.BuildServiceProvider(); + /// + /// Configure the PoCo the dependency injection + /// + /// services + /// + /// + public static AppSettings ConfigurePoCoAppSettings(IServiceCollection services, + IConfigurationRoot configuration) + { + // configs + services.ConfigurePoCo(configuration.GetSection("App")); - return serviceProvider.GetRequiredService(); - } + // Need to rebuild for AppSettings + var serviceProvider = services.BuildServiceProvider(); + + return serviceProvider.GetRequiredService(); } } diff --git a/starsky/starsky.foundation.readmeta/ReadMetaHelpers/ReadMetaGpx.cs b/starsky/starsky.foundation.readmeta/ReadMetaHelpers/ReadMetaGpx.cs index fc7d090aa..b54559149 100644 --- a/starsky/starsky.foundation.readmeta/ReadMetaHelpers/ReadMetaGpx.cs +++ b/starsky/starsky.foundation.readmeta/ReadMetaHelpers/ReadMetaGpx.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Globalization; using System.IO; -using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml; @@ -13,226 +12,220 @@ using starsky.foundation.readmeta.Models; using starsky.foundation.storage.Helpers; -namespace starsky.foundation.readmeta.ReadMetaHelpers +namespace starsky.foundation.readmeta.ReadMetaHelpers; + +public sealed class ReadMetaGpx { - public sealed class ReadMetaGpx + private const string GpxXmlNameSpaceName = "http://www.topografix.com/GPX/1/1"; + private readonly IWebLogger _logger; + + public ReadMetaGpx(IWebLogger logger) { - private readonly IWebLogger _logger; + _logger = logger; + } - public ReadMetaGpx(IWebLogger logger) + public async Task ReadGpxFromFileReturnAfterFirstFieldAsync(Stream? stream, + string subPath, bool useLocal = true) + { + if ( stream == null ) { - _logger = logger; + var returnItem = new FileIndexItem(subPath) + { + Status = FileIndexItem.ExifStatus.OperationNotSupported + }; + return returnItem; } - private const string GpxXmlNameSpaceName = "http://www.topografix.com/GPX/1/1"; + var readGpxFile = await ReadGpxFileAsync(stream, null, 1); - public async Task ReadGpxFromFileReturnAfterFirstFieldAsync(Stream? stream, - string subPath, bool useLocal = true) + if ( readGpxFile.Count == 0 ) { - if ( stream == null ) - { - var returnItem = new FileIndexItem(subPath) - { - Status = FileIndexItem.ExifStatus.OperationNotSupported - }; - return returnItem; - } - - var readGpxFile = await ReadGpxFileAsync(stream, null, 1); - - if ( readGpxFile.Count == 0 ) - { - _logger.LogInformation($"[ReadMetaGpx] SystemXmlXmlException for {subPath}"); - return new FileIndexItem(subPath) - { - Tags = "SystemXmlXmlException", - ColorClass = ColorClassParser.Color.None - }; - } - - var title = readGpxFile.FirstOrDefault()?.Title ?? string.Empty; - var dateTime = readGpxFile.FirstOrDefault()?.DateTime ?? - new DateTime(0, DateTimeKind.Utc); - var latitude = readGpxFile.FirstOrDefault()?.Latitude ?? 0d; - var longitude = readGpxFile.FirstOrDefault()?.Longitude ?? 0d; - var altitude = readGpxFile.FirstOrDefault()?.Altitude ?? 0d; - + _logger.LogInformation($"[ReadMetaGpx] SystemXmlXmlException for {subPath}"); return new FileIndexItem(subPath) { - Title = title, - DateTime = ConvertDateTime(dateTime, useLocal, latitude, longitude), - Latitude = latitude, - Longitude = longitude, - LocationAltitude = altitude, - ColorClass = ColorClassParser.Color.None, - ImageFormat = ExtensionRolesHelper.ImageFormat.gpx + Tags = "SystemXmlXmlException", ColorClass = ColorClassParser.Color.None }; } - internal static DateTime ConvertDateTime(DateTime dateTime, bool useLocal, - double latitude, double longitude) + var latitude = readGpxFile[0].Latitude; + var longitude = readGpxFile[0].Longitude; + var altitude = readGpxFile[0].Altitude; + + return new FileIndexItem(subPath) { - if ( !useLocal ) - { - return dateTime; - } + Title = readGpxFile[0].Title, + DateTime = ConvertDateTime(readGpxFile[0].DateTime, useLocal, latitude, longitude), + Latitude = latitude, + Longitude = longitude, + LocationAltitude = altitude, + ColorClass = ColorClassParser.Color.None, + ImageFormat = ExtensionRolesHelper.ImageFormat.gpx + }; + } - var localTimeZoneNameResult = TimeZoneLookup - .GetTimeZone(latitude, longitude).Result; - var localTimeZone = - TimeZoneInfo.FindSystemTimeZoneById(localTimeZoneNameResult); - return TimeZoneInfo.ConvertTimeFromUtc(dateTime, localTimeZone); + internal static DateTime ConvertDateTime(DateTime dateTime, bool useLocal, + double latitude, double longitude) + { + if ( !useLocal ) + { + return dateTime; } - private static string GetTrkName(XmlNode? gpxDoc, XmlNamespaceManager namespaceManager) + var localTimeZoneNameResult = TimeZoneLookup + .GetTimeZone(latitude, longitude).Result; + var localTimeZone = + TimeZoneInfo.FindSystemTimeZoneById(localTimeZoneNameResult); + return TimeZoneInfo.ConvertTimeFromUtc(dateTime, localTimeZone); + } + + private static string GetTrkName(XmlNode? gpxDoc, XmlNamespaceManager namespaceManager) + { + var trkNodeList = gpxDoc?.SelectNodes("//x:trk", namespaceManager); + if ( trkNodeList == null ) { - var trkNodeList = gpxDoc?.SelectNodes("//x:trk", namespaceManager); - if ( trkNodeList == null ) - { - return string.Empty; - } + return string.Empty; + } - var trkName = new StringBuilder(); - foreach ( XmlElement node in trkNodeList ) + var trkName = new StringBuilder(); + foreach ( XmlElement node in trkNodeList ) + { + foreach ( XmlElement childNode in node.ChildNodes ) { - foreach ( XmlElement childNode in node.ChildNodes ) + if ( childNode.Name != "name" ) { - if ( childNode.Name != "name" ) - { - continue; - } - - trkName.Append(childNode.InnerText); - return trkName.ToString(); + continue; } - } - return string.Empty; + trkName.Append(childNode.InnerText); + return trkName.ToString(); + } } - /// - /// Read full gpx file, or return after trackPoint - /// - /// - /// - /// default complete file, but can be used to read only the first point - /// - public async Task> ReadGpxFileAsync(Stream stream, - List? geoList = null, int returnAfter = int.MaxValue) - { - geoList ??= new List(); + return string.Empty; + } - // Some files are having problems with gpxDoc.Load() - // Stream is disposed in the StreamToStringHelper - var fileString = await StreamToStringHelper.StreamToStringAsync(stream); + /// + /// Read full gpx file, or return after trackPoint + /// + /// + /// + /// default complete file, but can be used to read only the first point + /// + public async Task> ReadGpxFileAsync(Stream stream, + List? geoList = null, int returnAfter = int.MaxValue) + { + geoList ??= new List(); - try - { - return ParseGpxString(fileString, geoList, returnAfter); - } - catch ( XmlException e ) - { - _logger.LogInformation($"XmlException for {e}"); - return geoList; - } - } + // Some files are having problems with gpxDoc.Load() + // Stream is disposed in the StreamToStringHelper + var fileString = await StreamToStringHelper.StreamToStringAsync(stream); - /// - /// Parse XML as XmlDocument - /// - /// input as string - /// parsed xml document - internal static XmlDocument ParseXml(string fileString) + try { - XmlDocument gpxDoc = new XmlDocument(); - gpxDoc.LoadXml(fileString); - return gpxDoc; + return ParseGpxString(fileString, geoList, returnAfter); } - - /// - /// Parse the gpx string - /// - /// string with xml - /// object to add - /// return after number of values; default return all - /// - private static List ParseGpxString(string fileString, - List? geoList = null, - int returnAfter = int.MaxValue) + catch ( XmlException e ) { - var gpxDoc = ParseXml(fileString); + _logger.LogInformation($"XmlException for {e}"); + return geoList; + } + } - XmlNamespaceManager namespaceManager = new XmlNamespaceManager(gpxDoc.NameTable); - namespaceManager.AddNamespace("x", GpxXmlNameSpaceName); + /// + /// Parse XML as XmlDocument + /// + /// input as string + /// parsed xml document + internal static XmlDocument ParseXml(string fileString) + { + var gpxDoc = new XmlDocument(); + gpxDoc.LoadXml(fileString); + return gpxDoc; + } - XmlNodeList? nodeList = gpxDoc.SelectNodes("//x:trkpt", namespaceManager); - if ( nodeList == null ) - { - return new List(); - } + /// + /// Parse the gpx string + /// + /// string with xml + /// object to add + /// return after number of values; default return all + /// + private static List ParseGpxString(string fileString, + List? geoList = null, + int returnAfter = int.MaxValue) + { + var gpxDoc = ParseXml(fileString); - geoList ??= new List(); + var namespaceManager = new XmlNamespaceManager(gpxDoc.NameTable); + namespaceManager.AddNamespace("x", GpxXmlNameSpaceName); - var title = GetTrkName(gpxDoc, namespaceManager); + var nodeList = gpxDoc.SelectNodes("//x:trkpt", namespaceManager); + if ( nodeList == null ) + { + return new List(); + } - var count = 0; - foreach ( XmlElement node in nodeList ) - { - var longitudeString = node.GetAttribute("lon"); - var latitudeString = node.GetAttribute("lat"); + geoList ??= new List(); - var longitude = double.Parse(longitudeString, - NumberStyles.Currency, CultureInfo.InvariantCulture); - var latitude = double.Parse(latitudeString, - NumberStyles.Currency, CultureInfo.InvariantCulture); + var title = GetTrkName(gpxDoc, namespaceManager); - DateTime dateTime = DateTime.MinValue; + var count = 0; + foreach ( XmlElement node in nodeList ) + { + var longitudeString = node.GetAttribute("lon"); + var latitudeString = node.GetAttribute("lat"); - var elevation = 0d; + var longitude = double.Parse(longitudeString, + NumberStyles.Currency, CultureInfo.InvariantCulture); + var latitude = double.Parse(latitudeString, + NumberStyles.Currency, CultureInfo.InvariantCulture); - foreach ( XmlElement childNode in node.ChildNodes ) - { - if ( childNode.Name == "ele" ) - { - elevation = double.Parse(childNode.InnerText, CultureInfo.InvariantCulture); - } - - if ( childNode.Name != "time" ) - { - continue; - } - - var datetimeString = childNode.InnerText; - - // 2018-08-21T19:15:41Z - DateTime.TryParseExact(datetimeString, - "yyyy-MM-ddTHH:mm:ssZ", - CultureInfo.InvariantCulture, - DateTimeStyles.AdjustToUniversal, - out dateTime); - - dateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Utc); - } + var dateTime = DateTime.MinValue; + var elevation = 0d; - geoList.Add(new GeoListItem + foreach ( XmlElement childNode in node.ChildNodes ) + { + if ( childNode.Name == "ele" ) { - Title = title, - DateTime = dateTime, - Latitude = latitude, - Longitude = longitude, - Altitude = elevation - }); - - if ( returnAfter == count ) + elevation = double.Parse(childNode.InnerText, CultureInfo.InvariantCulture); + } + + if ( childNode.Name != "time" ) { - return geoList; + continue; } - count++; + var datetimeString = childNode.InnerText; + + // 2018-08-21T19:15:41Z + DateTime.TryParseExact(datetimeString, + "yyyy-MM-ddTHH:mm:ssZ", + CultureInfo.InvariantCulture, + DateTimeStyles.AdjustToUniversal, + out dateTime); + + dateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Utc); } - return geoList; + + geoList.Add(new GeoListItem + { + Title = title, + DateTime = dateTime, + Latitude = latitude, + Longitude = longitude, + Altitude = elevation + }); + + if ( returnAfter == count ) + { + return geoList; + } + + count++; } + + return geoList; } } diff --git a/starsky/starsky/Controllers/MetaUpdateController.cs b/starsky/starsky/Controllers/MetaUpdateController.cs index b669774e8..4478f199f 100644 --- a/starsky/starsky/Controllers/MetaUpdateController.cs +++ b/starsky/starsky/Controllers/MetaUpdateController.cs @@ -82,7 +82,7 @@ public async Task UpdateAsync(FileIndexItem inputModel, string f, var (fileIndexResultsList, changedFileIndexItemName) = await _metaPreflight.PreflightAsync(inputModel, - inputFilePaths.ToList(), append, collections, rotateClock); + [.. inputFilePaths], append, collections, rotateClock); // Update > await _bgTaskQueue.QueueBackgroundWorkItemAsync(async _ => @@ -107,7 +107,7 @@ await metaUpdateService.UpdateAsync( return NotFound(fileIndexResultsList); } - // Clone an new item in the list to display + // Clone a new item in the list to display var returnNewResultList = fileIndexResultsList.Select(item => item.Clone()).ToList(); // when switching very fast between images the background task has not run yet @@ -115,7 +115,7 @@ await metaUpdateService.UpdateAsync( // Push direct to socket when update or replace to avoid undo after a second _logger.LogInformation( - $"[UpdateController] send to socket {inputFilePaths.FirstOrDefault()}"); + $"[UpdateController] send to socket {inputFilePaths[0]}"); await Task.Run(async () => await UpdateWebSocketTaskRun(fileIndexResultsList));