Small cleaning refactor in TFSAggregatorSettings

--- Configuration/TFSAggregatorSettings.cs
+++ Configuration/TFSAggregatorSettings.cs
@@ -40,22 +40,53 @@
             LoadOptions xmlLoadOptions = LoadOptions.PreserveWhitespace | LoadOptions.SetBaseUri | LoadOptions.SetLineInfo;
             XDocument doc = load(xmlLoadOptions);

+            if (!Validate(logger, doc))
+                // HACK we must handle this scenario with clean exit
+                return null;
+
+            // XML Schema has done lot of checking and set defaults, no need to recheck later, just manage missing pieces
+
+            ParseRuntime(instance, doc);
+
+            Dictionary<string, Rule> rules = ParseRules(instance, doc);
+
+            var ruleInUse = new Dictionary<string, bool>();
+            foreach (string ruleName in rules.Keys)
+            {
+                ruleInUse.Add(ruleName, false);
+            }//for
+
+            List<Policy> policies = ParsePolicies(doc, rules, ruleInUse);
+
+            instance.Policies = policies;
+
+            // checks
+            foreach (var unusedRule in ruleInUse.Where(kv => kv.Value == false))
+            {
+                logger.UnreferencedRule(unusedRule.Key);
+            }//for
+
+            return instance;
+        }
+
+        private static bool Validate(ILogEvents logger, XDocument doc)
+        {
             XmlSchemaSet schemas = new XmlSchemaSet();
             var thisAssembly = Assembly.GetAssembly(typeof(TFSAggregatorSettings));
             var stream = thisAssembly.GetManifestResourceStream("Aggregator.Core.Configuration.AggregatorConfiguration.xsd");
             schemas.Add("", XmlReader.Create(stream));
-            bool errors = false;
+            bool valid = true;
             doc.Validate(schemas, (o, e) =>
             {
                 logger.InvalidConfiguration(e.Severity, e.Message, e.Exception.LineNumber, e.Exception.LinePosition);
-                errors = true;
+                valid = false;
             }, true);
-            if (errors)
-                // HACK we must handle this scenario with clean exit
-                return null;
-
-            // XML Schema has done lot of checking and set defaults, no need to recheck here
-            var loggingNode = doc.Root.Element("runtime") != null ?
+            return valid;
+        }
+
+        private static void ParseRuntime(TFSAggregatorSettings instance, XDocument doc)
+        {
+            var loggingNode = doc.Root.Element("runtime") != null ?
                 doc.Root.Element("runtime").Element("logging") : null;
             instance.LogLevel = loggingNode != null ?
                 (LogLevel)Enum.Parse(typeof(LogLevel), loggingNode.Attribute("level").Value)
@@ -70,26 +101,6 @@
             instance.ScriptLanguage = scriptNode != null ?
                 scriptNode.Attribute("language").Value
                 : "C#";
-
-            Dictionary<string, Rule> rules = ParseRules(instance, doc);
-
-            var ruleInUse = new Dictionary<string, bool>();
-            foreach (string ruleName in rules.Keys)
-            {
-                ruleInUse.Add(ruleName, false);
-            }//for
-
-            List<Policy> policies = ParsePolicies(doc, rules, ruleInUse);
-
-            instance.Policies = policies;
-
-            // checks
-            foreach (var unusedRule in ruleInUse.Where(kv => kv.Value == false))
-            {
-                logger.UnreferencedRule(unusedRule.Key);
-            }//for
-
-            return instance;
         }

         private static List<Policy> ParsePolicies(XDocument doc, Dictionary<string, Rule> rules, Dictionary<string, bool> ruleInUse)


#372 Add unit tests for SimpleContainer

#372 Add unit tests for SimpleContainer

--- src/Caliburn.Micro.Core.Tests/SimpleContainerTests.cs
+++ src/Caliburn.Micro.Core.Tests/SimpleContainerTests.cs
@@ -123,4 +123,93 @@
             Assert.Equal(2, results.Count());
         }
     }
+
+    public class SimpleContainer_Find_Constructor
+    {
+
+        public class SingleEmptyConstructorType
+        {
+            public SingleEmptyConstructorType()
+            {
+
+            }
+        }
+
+        [Fact]
+        public void Container_Finds_Single_Constructor()
+        {
+            var container = new SimpleContainer();
+            container.Singleton<SingleEmptyConstructorType>();
+            container.GetInstance(typeof(SingleEmptyConstructorType), null);
+        }
+
+        public class SingleNonEmptyConstructorType
+        {
+            public SingleNonEmptyConstructorType(SimpleContainer_Find_Constructor.SingleEmptyConstructorType type)
+            {
+            }
+        }
+
+        [Fact]
+        public void Container_No_EmptyConstructor()
+        {
+            var container = new SimpleContainer();
+            container.Singleton<SingleNonEmptyConstructorType>();
+            container.GetInstance(typeof(SingleNonEmptyConstructorType), null);
+        }
+
+        public class SingleIntConstructor
+        {
+            public int Value { get; private set; }
+
+            public SingleIntConstructor(int x)
+            {
+                this.Value = x;
+            }
+        }
+
+        [Fact]
+        public void Container_SingleIntConstructor()
+        {
+            var container = new SimpleContainer();
+            container.Singleton<SingleIntConstructor>();
+            container.RegisterInstance(typeof(int), "x", 4);
+            var inst = (SingleIntConstructor)container.GetInstance(typeof(SingleIntConstructor), null);
+            Assert.Equal(4, inst.Value);
+        }
+
+        public class TwoConstructors
+        {
+            public int Value { get; set; }
+
+            public TwoConstructors()
+            {
+                this.Value = 42;
+            }
+
+            public TwoConstructors(int value)
+            {
+                Value = value;
+            }
+        }
+
+        [Fact]
+        public void Container_ChooseConstructorWithRegisteredParameter()
+        {
+            var container = new SimpleContainer();
+            container.Singleton<TwoConstructors>();
+            container.RegisterInstance(typeof(int), null, 23);
+            var inst = (TwoConstructors)container.GetInstance(typeof(TwoConstructors), null);
+            Assert.Equal(23, inst.Value);
+        }
+
+        [Fact]
+        public void Container_ChooseEmptyConstructorWithoutRegisteredParameter()
+        {
+            var container = new SimpleContainer();
+            container.Singleton<TwoConstructors>();
+            var inst = (TwoConstructors)container.GetInstance(typeof(TwoConstructors), null);
+            Assert.Equal(42, inst.Value);
+        }
+    }
 }


strtotime() fix for DST invalid times

strtotime() fix for DST invalid times

- faster impl. that offsets the time to UTC based on TZ and DST (using TimeZoneInfo AdjustmentRules)
- ignores invalid times as it is in PHP

--- src/Peachpie.Library/DateTime/DateTimeFunctions.cs
+++ src/Peachpie.Library/DateTime/DateTimeFunctions.cs
@@ -1517,7 +1517,14 @@

             if (error == null)
             {
-                var utctime = TimeZoneInfo.ConvertTimeToUtc(result, localtz);
+                //var utctime = TimeZoneInfo.ConvertTimeToUtc(result, localtz); // throws on invalid date, i.e. in DST
+
+                var offset = result.Kind != DateTimeKind.Utc && localtz != TimeZoneInfo.Utc
+                    ? localtz.GetUtcOffset(result)
+                    : TimeSpan.Zero;
+
+                var utctime = new System_DateTime(result.Ticks - offset.Ticks);
+
                 return DateTimeUtils.UtcToUnixTimeStamp(utctime);
             }
             else


Fix connection leak during redirections

Fix connection leak during redirections

--- src/Core/HttpQuery.cs
+++ src/Core/HttpQuery.cs
@@ -93,77 +93,86 @@
                 Content = content
             };

-            var response = await http.SendAsync(request, config, options)
-                                     .DontContinueOnCapturedContext();
-
-            IEnumerable<string> cookies;
-            if (response.Headers.TryGetValues("Set-Cookie", out cookies))
-            {
-                var cc = new CookieContainer();
-                foreach (var cookie in http.Config.Cookies ?? Enumerable.Empty<Cookie>())
-                    cc.Add(cookie);
-                foreach (var cookie in cookies)
+            HttpResponseMessage response = null;
+
+            try
+            {
+                response = await http.SendAsync(request, config, options)
+                    .DontContinueOnCapturedContext();
+
+                IEnumerable<string> cookies;
+                if (response.Headers.TryGetValues("Set-Cookie", out cookies))
                 {
-                    try { cc.SetCookies(url, cookie); }
-                    catch (CookieException) { /* ignore bad cookies */}
+                    var cc = new CookieContainer();
+                    foreach (var cookie in http.Config.Cookies ?? Enumerable.Empty<Cookie>())
+                        cc.Add(cookie);
+                    foreach (var cookie in cookies)
+                    {
+                        try { cc.SetCookies(url, cookie); }
+                        catch (CookieException) { /* ignore bad cookies */}
+                    }
+                    config = config.WithCookies(cc.GetCookies(url).Cast<Cookie>().ToArray());
                 }
-                config = config.WithCookies(cc.GetCookies(url).Cast<Cookie>().ToArray());
+
+                // Source:
+                // https://referencesource.microsoft.com/#System/net/System/Net/HttpWebRequest.cs,5669
+                //
+                // Check for Redirection
+                //
+                // Table View:
+                // Method            301             302             303             307
+                //    *                *               *             GET               *
+                // POST              GET             GET             GET            POST
+                //
+                // Put another way:
+                //  301 & 302  - All methods are redirected to the same method but POST. POST is redirected to a GET.
+                //  303 - All methods are redirected to GET
+                //  307 - All methods are redirected to the same method.
+                //
+
+                var sc = response.StatusCode;
+                if (sc == HttpStatusCode.Ambiguous || // 300
+                    sc == HttpStatusCode.Moved || // 301
+                    sc == HttpStatusCode.Redirect || // 302
+                    sc == HttpStatusCode.RedirectMethod || // 303
+                    sc == HttpStatusCode.RedirectKeepVerb) // 307
+                {
+                    var redirectionUrl = response.Headers.Location?.AsRelativeTo(response.RequestMessage.RequestUri);
+                    if (redirectionUrl == null)
+                    {
+                        // 300
+                        // If the server has a preferred choice of representation,
+                        // it SHOULD include the specific URI for that
+                        // representation in the Location field; user agents MAY
+                        // use the Location field value for automatic redirection.
+
+                        if (sc != HttpStatusCode.Ambiguous)
+                            throw new ProtocolViolationException("Server did not supply a URL for a redirection response.");
+                    }
+                    else
+                    {
+                        if (redirectionUrl.Scheme == "ws" || redirectionUrl.Scheme == "wss")
+                            throw new NotSupportedException($"Redirection to a WebSocket URL ({redirectionUrl}) is not supported.");
+
+                        if (redirectionUrl.Scheme != Uri.UriSchemeHttp && redirectionUrl.Scheme != Uri.UriSchemeHttps)
+                            throw new ProtocolViolationException(
+                                $"Server sent a redirection response where the redirection URL ({redirectionUrl}) scheme was neither HTTP nor HTTPS.");
+
+                        return sc == HttpStatusCode.RedirectMethod
+                            || method == HttpMethod.Post && (sc == HttpStatusCode.Moved || sc == HttpStatusCode.Redirect)
+                             ? redirectionSelector(config, HttpMethod.Get, redirectionUrl, null)
+                             : redirectionSelector(config, method, redirectionUrl, content);
+                    }
+                }
+
+                var result = responseSelector(config, response);
+                response = null; // disown
+                return result;
             }
-
-            // Source:
-            // https://referencesource.microsoft.com/#System/net/System/Net/HttpWebRequest.cs,5669
-            //
-            // Check for Redirection
-            //
-            // Table View:
-            // Method            301             302             303             307
-            //    *                *               *             GET               *
-            // POST              GET             GET             GET            POST
-            //
-            // Put another way:
-            //  301 & 302  - All methods are redirected to the same method but POST. POST is redirected to a GET.
-            //  303 - All methods are redirected to GET
-            //  307 - All methods are redirected to the same method.
-            //
-
-            var sc = response.StatusCode;
-            if (sc == HttpStatusCode.Ambiguous || // 300
-                sc == HttpStatusCode.Moved || // 301
-                sc == HttpStatusCode.Redirect || // 302
-                sc == HttpStatusCode.RedirectMethod || // 303
-                sc == HttpStatusCode.RedirectKeepVerb) // 307
-            {
-                var redirectionUrl = response.Headers.Location?.AsRelativeTo(response.RequestMessage.RequestUri);
-                if (redirectionUrl == null)
-                {
-                    // 300
-                    // If the server has a preferred choice of representation,
-                    // it SHOULD include the specific URI for that
-                    // representation in the Location field; user agents MAY
-                    // use the Location field value for automatic redirection.
-
-                    if (sc != HttpStatusCode.Ambiguous)
-                        throw new ProtocolViolationException("Server did not supply a URL for a redirection response.");
-                }
-                else
-                {
-                    if (redirectionUrl.Scheme == "ws" || redirectionUrl.Scheme == "wss")
-                        throw new NotSupportedException($"Redirection to a WebSocket URL ({redirectionUrl}) is not supported.");
-
-                    if (redirectionUrl.Scheme != Uri.UriSchemeHttp && redirectionUrl.Scheme != Uri.UriSchemeHttps)
-                        throw new ProtocolViolationException(
-                            $"Server sent a redirection response where the redirection URL ({redirectionUrl}) scheme was neither HTTP nor HTTPS.");
-
-                    return sc == HttpStatusCode.RedirectMethod
-                        || method == HttpMethod.Post && (sc == HttpStatusCode.Moved || sc == HttpStatusCode.Redirect)
-                         ? redirectionSelector(config, HttpMethod.Get, redirectionUrl, null)
-                         : redirectionSelector(config, method, redirectionUrl, content);
-
-                }
-
+            finally
+            {
+                response?.Dispose();
             }
-
-            return responseSelector(config, response);
         }

         public static IHttpObservable Get(this IHttpObservable query, Uri url) =>


datetime: array output perf

datetime: array output perf

--- src/Peachpie.Library/DateTime/DateTimeFunctions.cs
+++ src/Peachpie.Library/DateTime/DateTimeFunctions.cs
@@ -1600,7 +1600,7 @@

             if (dateinfo.have_relative != 0)
             {
-                result["relative"] = new PhpArray(6)
+                result["relative"] = new PhpArray(7)
                 {
                     //[year] => 0
                     { "year", dateinfo.relative.y },


Pre-Selects the item in the Explorer

Pre-Selects the item in the Explorer

--- src/DatenMeister.WPF/Forms/Lists/ItemsInExtentList.cs
+++ src/DatenMeister.WPF/Forms/Lists/ItemsInExtentList.cs
@@ -15,6 +15,7 @@
 using DatenMeister.Modules.ChangeEvents;
 using DatenMeister.Modules.Forms.FormFinder;
 using DatenMeister.Runtime.Extents;
+using DatenMeister.Runtime.ExtentStorage;
 using DatenMeister.Runtime.ExtentStorage.Configuration;
 using DatenMeister.Runtime.ExtentStorage.Interfaces;
 using DatenMeister.Runtime.Workspaces;
@@ -281,8 +282,11 @@
                 if (extentManager.GetLoadConfigurationFor(uriExtent) is ExtentFileLoaderConfig
                         loadConfiguration && loadConfiguration.filePath != null)
                 {
-                    // ReSharper disable once AssignNullToNotNullAttribute
-                    Process.Start(Path.GetDirectoryName(loadConfiguration.filePath));
+                    var filePath = loadConfiguration.filePath;
+
+                    //Clean up file path so it can be navigated OK
+                    filePath = Path.GetFullPath(filePath);
+                    Process.Start("explorer.exe", $"/select,\"{filePath}\"");
                 }
                 else
                 {


test json serializer default settings

test json serializer default settings

--- Cowboy.Serialization/JsonSerializer.cs
+++ Cowboy.Serialization/JsonSerializer.cs
@@ -2,6 +2,7 @@
 using System.Collections.Generic;
 using System.IO;
 using System.Text;
+using Newtonsoft.Json;

 namespace Cowboy.Serialization
 {
@@ -11,7 +12,25 @@

         public JsonSerializer()
         {
-            _serializer = Newtonsoft.Json.JsonSerializer.CreateDefault();
+            var settings = new JsonSerializerSettings()
+            {
+                ConstructorHandling = ConstructorHandling.Default,
+                DateFormatHandling = DateFormatHandling.IsoDateFormat,
+                DateParseHandling = DateParseHandling.DateTime,
+                DefaultValueHandling = DefaultValueHandling.Include,
+                FloatFormatHandling = FloatFormatHandling.DefaultValue,
+                FloatParseHandling = FloatParseHandling.Decimal,
+                Formatting = Formatting.None,
+                MetadataPropertyHandling = MetadataPropertyHandling.Default,
+                MissingMemberHandling = MissingMemberHandling.Ignore,
+                NullValueHandling = NullValueHandling.Ignore,
+                ObjectCreationHandling = ObjectCreationHandling.Auto,
+                PreserveReferencesHandling = PreserveReferencesHandling.None,
+                ReferenceLoopHandling = ReferenceLoopHandling.Error,
+                StringEscapeHandling = StringEscapeHandling.Default,
+                TypeNameHandling = TypeNameHandling.None,
+            };
+            _serializer = Newtonsoft.Json.JsonSerializer.CreateDefault(settings);
         }

         public bool CanSerialize(string contentType)


update charts

update charts

--- CrossPlatform/BTTP/Views/GraphsPage.cs
+++ CrossPlatform/BTTP/Views/GraphsPage.cs
@@ -1,6 +1,8 @@
 using System;
 using System.Collections.Generic;
+using System.Globalization;
 using System.Text;
+using System.Threading;
 using OxyPlot;
 using OxyPlot.Axes;
 using OxyPlot.Series;
@@ -64,44 +66,46 @@
             };
         }

+        private static String DATE_FORMAT = "dd-MMM";
+
         private PlotModel CaloriesCreatePlotModel()
         {
             CalorieStreamViewModel calorieStream = new CalorieStreamViewModel();
             var plotModel = new PlotModel();

-            plotModel.Axes.Add(new DateTimeAxis
-            {
-                Position = AxisPosition.Bottom,
-                StringFormat = "yyyy-MM-dd",
-                Title = "Date"
-            });
-
             plotModel.Axes.Add(new LinearAxis
             {
                 Position = AxisPosition.Left,
-                Maximum = 10000,
-                Minimum = 0,
                 Title = "Calories (kcal)"
             });

-            var series1 = new ScatterSeries()
+            var series = new ColumnSeries()
             {
-                MarkerType = MarkerType.Circle,
-                MarkerSize = 6,
-                MarkerStroke = OxyColors.White
+                Background = OxyColor.FromRgb(135, 206, 250), // blue
+                FillColor = OxyColor.FromRgb(255, 165, 0)     // orange
             };

             List<Entry> entries = calorieStream.GetEntries();
+            CategoryAxis categoryAxis = new CategoryAxis()
+            {
+                Position = AxisPosition.Bottom,
+                StringFormat = DATE_FORMAT,
+                Title = "Date"
+            };
+
+            CultureInfo culture = new CultureInfo("en-GB");

             if (entries != null)
             {
                 foreach (var entry in entries)
                 {
-                    series1.Points.Add(new ScatterPoint(DateTimeAxis.ToDouble(entry.date), entry.value));
+                    series.Items.Add(new ColumnItem(entry.value));
+                    categoryAxis.Labels.Add(entry.date.ToString(DATE_FORMAT, culture));
                 }
             }

-            plotModel.Series.Add(series1);
+            plotModel.Axes.Add(categoryAxis);
+            plotModel.Series.Add(series);

             return plotModel;
         }
@@ -111,26 +115,26 @@
             HeartRateStreamViewModel heartRateStream = new HeartRateStreamViewModel();
             var plotModel = new PlotModel();

+            plotModel.Axes.Add(new LinearAxis
+            {
+                Position = AxisPosition.Left,
+                Title = "BPM"
+            });
+
             plotModel.Axes.Add(new DateTimeAxis
             {
                 Position = AxisPosition.Bottom,
-                StringFormat = "yyyy-MM-dd",
-                Title = "Date"
+                Title = "Date",
+                StringFormat = DATE_FORMAT,
             });

-            plotModel.Axes.Add(new LinearAxis
-            {
-                Position = AxisPosition.Left,
-                Maximum = 200,
-                Minimum = 0,
-                Title = "BPM"
-            });
-
-            var series1 = new ScatterSeries()
+            var series = new ScatterSeries()
             {
                 MarkerType = MarkerType.Circle,
-                MarkerSize = 6,
-                MarkerStroke = OxyColors.White
+                MarkerSize = 4,
+                MarkerStroke = OxyColor.FromRgb(255, 165, 0),  // orange,
+                MarkerFill = OxyColor.FromRgb(255, 165, 0),  // orange
+                Background = OxyColor.FromRgb(135, 206, 250),  // blue
             };

             List<Entry> entries = heartRateStream.GetEntries();
@@ -139,11 +143,11 @@
             {
                 foreach (var entry in entries)
                 {
-                    series1.Points.Add(new ScatterPoint(DateTimeAxis.ToDouble(entry.date), entry.value));
+                    series.Points.Add(new ScatterPoint(DateTimeAxis.ToDouble(entry.date), entry.value));
                 }
             }

-            plotModel.Series.Add(series1);
+            plotModel.Series.Add(series);

             return plotModel;
         }
@@ -153,37 +157,39 @@
             DistancesStreamViewModel distancesStream = new DistancesStreamViewModel();
             var plotModel = new PlotModel();

-            plotModel.Axes.Add(new DateTimeAxis
-            {
-                Position = AxisPosition.Bottom,
-                StringFormat = "yyyy-MM-dd",
-                Title = "Date"
-            });
-
             plotModel.Axes.Add(new LinearAxis
             {
                 Position = AxisPosition.Left,
                 Title = "Distance (m)"
             });

-            var series1 = new ScatterSeries()
+            var series = new ColumnSeries()
             {
-                MarkerType = MarkerType.Circle,
-                MarkerSize = 6,
-                MarkerStroke = OxyColors.White
+                Background = OxyColor.FromRgb(135, 206, 250), // blue
+                FillColor = OxyColor.FromRgb(255, 165, 0)     // orange
             };

             List<Entry> entries = distancesStream.GetEntries();
+            CategoryAxis categoryAxis = new CategoryAxis()
+            {
+                Position = AxisPosition.Bottom,
+                StringFormat = DATE_FORMAT,
+                Title = "Date"
+            };
+
+            CultureInfo culture = new CultureInfo("en-GB");

             if (entries != null)
             {
                 foreach (var entry in entries)
                 {
-                    series1.Points.Add(new ScatterPoint(DateTimeAxis.ToDouble(entry.date), entry.value / 1000.0));
+                    series.Items.Add(new ColumnItem((int)(entry.value / 1000.0)));
+                    categoryAxis.Labels.Add(entry.date.ToString(DATE_FORMAT, culture));
                 }
             }

-            plotModel.Series.Add(series1);
+            plotModel.Axes.Add(categoryAxis);
+            plotModel.Series.Add(series);

             return plotModel;
         }


320: lazy init of _signature

320: lazy init of _signature

--- src/SharpConnect.MySql/0_Public/MySqlConnection.cs
+++ src/SharpConnect.MySql/0_Public/MySqlConnection.cs
@@ -59,9 +59,7 @@
             Username = u;
             Password = p;
             Database = d;
-            PortNumber = portNumber;//default mysql port
-
-            _signature = string.Concat(h, u, d, PortNumber).GetHashCode();
+            PortNumber = portNumber;//default mysql port
         }
         public string Host { get; private set; }
         public string Username { get; private set; }
@@ -71,8 +69,8 @@
         internal int ConnSignature
         {
             get
-            {
-                return _signature;
+            {
+                return (_signature != 0)? _signature: _signature = string.Concat(Host, Username, Database, PortNumber).GetHashCode();
             }
         }
         public static MySqlConnectionString Parse(string connString)


add error handling to create method

add error handling to create method

--- src/Sir.HttpServer/Controllers/CreateController.cs
+++ src/Sir.HttpServer/Controllers/CreateController.cs
@@ -95,31 +95,40 @@
             var queryId = Guid.NewGuid().ToString();
             var userDirectory = Path.Combine(Config.Get("user_dir"), queryId);

-            if (!Directory.Exists(userDirectory))
+            try
             {
+                if (Directory.Exists(userDirectory))
+                {
+                    return new ConflictResult();
+                }
+
                 Directory.CreateDirectory(userDirectory);
-            }

-            var urlCollectionId = "url".ToHash();
-            var documents = new List<Document>();
+                var urlCollectionId = "url".ToHash();
+                var documents = new List<Document>();

-            foreach (var uri in uris)
-            {
-                documents.Add(new Document(new Field[]
+                foreach (var uri in uris)
                 {
+                    documents.Add(new Document(new Field[]
+                    {
                     new Field("url", uri.uri.ToString()),
                     new Field("host", uri.uri.Host),
                     new Field("scope", uri.scope),
                     new Field("verified", false)
-                }));
+                    }));
+                }
+
+                Database.Store(
+                    userDirectory,
+                    urlCollectionId,
+                    documents);
+
+                return RedirectToAction("Index", "Search", new { queryId });
             }
-
-            Database.Store(
-                userDirectory,
-                urlCollectionId,
-                documents);
-
-            return RedirectToAction("Index", "Search", new { queryId });
+            catch
+            {
+                return new ConflictResult();
+            }
         }
     }


try fix tests in travis

try fix tests in travis

--- src/SoapCore.Tests/Serialization/ServiceFixture.cs
+++ src/SoapCore.Tests/Serialization/ServiceFixture.cs
@@ -2,6 +2,7 @@
 using System.Collections.Generic;
 using System.IO;
 using System.ServiceModel;
+using System.Threading;
 using Microsoft.AspNetCore.Builder;
 using Microsoft.AspNetCore.Hosting;
 using Microsoft.Extensions.DependencyInjection;
@@ -9,7 +10,7 @@

 namespace SoapCore.Tests.Serialization
 {
-	public class ServiceFixture<IService> : IDisposable where IService : class
+	public class ServiceFixture<IService> : IDisposable where IService : class
 	{
 		public const int Port = 5060;
 		public Mock<IService> serviceMock { get; private set; }
@@ -55,7 +56,7 @@
 				.Build();

 #pragma warning disable 4014
-			host.RunAsync();
+			host.RunAsync().Wait(1000);
 #pragma warning restore 4014

 			// make service client


Fix null handling

Fix null handling

--- src/SourceCode.Clay.Buffers/ArrayBufferComparer.cs
+++ src/SourceCode.Clay.Buffers/ArrayBufferComparer.cs
@@ -66,9 +66,11 @@
         /// </returns>
         public override int GetHashCode(byte[] obj)
         {
-            ReadOnlySpan<byte> span = obj;
-            if (HashCodeFidelity > 0 && obj.Length > HashCodeFidelity)
-                span = new ReadOnlySpan<byte>(obj, 0, HashCodeFidelity);
+            if (obj == null) return HashCode.Fnv((byte[])null);
+
+            var span = new ReadOnlySpan<byte>(obj);
+            if (HashCodeFidelity > 0 && span.Length > HashCodeFidelity)
+                span = span.Slice(0, HashCodeFidelity);

             var fnv = HashCode.Fnv(span);
             return fnv;


Added unit tests for selenium

Added unit tests for selenium

--- src/SpecBind.Selenium.Tests/SeleniumPageFixture.cs
+++ src/SpecBind.Selenium.Tests/SeleniumPageFixture.cs
@@ -6,7 +6,7 @@
     using System;
     using System.Collections.ObjectModel;
     using System.Drawing;
-
+    using System.Linq;
     using Microsoft.VisualStudio.TestTools.UnitTesting;

     using Moq;
@@ -448,8 +448,15 @@
         [TestMethod]
         public void TestGetElementOptionsForComboBox()
         {
-            var element = new Mock<IWebElement>(MockBehavior.Strict);
-            element.SetupGet(e => e.TagName).Returns("text");
+            var optionElement = new Mock<IWebElement>(MockBehavior.Strict);
+            optionElement.SetupGet(e => e.Text).Returns("Option 1");
+            optionElement.Setup(e => e.GetAttribute("value")).Returns("0");
+
+            var element = new Mock<IWebElement>(MockBehavior.Strict);
+            element.SetupGet(e => e.TagName).Returns("select");
+            element.Setup(e => e.GetAttribute("multiple")).Returns("false");
+            element.Setup(e => e.FindElements(By.TagName("option")))
+                   .Returns((new IWebElement[] { optionElement.Object }).ToList().AsReadOnly());

             var nativePage = new NativePage();
             var page = new SeleniumPage(nativePage, null);
@@ -458,6 +465,11 @@

             Assert.IsNotNull(result);
             Assert.AreEqual(1, result.Count);
+
+            var option = result.First();
+            Assert.AreEqual("0", option.Value);
+            Assert.AreEqual("Option 1", option.Text);
+
             element.VerifyAll();
         }


Disable RecursiveDelete_DeepNesting (Issue #24242). (#24243)

--- src/System.IO.FileSystem/tests/Directory/Delete.cs
+++ src/System.IO.FileSystem/tests/Directory/Delete.cs
@@ -254,6 +254,7 @@
         }

         [Fact]
+        [ActiveIssue(24242)]
         [PlatformSpecific(TestPlatforms.Windows)]
         [OuterLoop("This test is very slow.")]
         [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "Desktop does not have the fix for #22596")]


Remove the URL from comment

Remove the URL from comment

--- src/System.Net.Primitives/src/System/Net/Cookie.cs
+++ src/System.Net.Primitives/src/System/Net/Cookie.cs
@@ -214,8 +214,7 @@
         }

 /*
-
-git push
+   VSO 449560
    Reflecting on internal method wont work on AOT without rd.xml and DisableReflection
    block in toolchain.Networking team will be working on exposing methods from S.Net.Primitive
    public,this is a temporary workaround till that happens.


Corrected exception message to display expected ServiceName

--- src/Topshelf/Runtime/Windows/WindowsServiceHost.cs
+++ src/Topshelf/Runtime/Windows/WindowsServiceHost.cs
@@ -66,7 +66,7 @@

             if (!_environment.IsServiceInstalled(_settings.ServiceName))
             {
-                string message = $"The {_settings} service has not been installed yet. Please run '{Assembly.GetEntryAssembly().GetName()} install'.";
+                string message = $"The {_settings.ServiceName} service has not been installed yet. Please run '{Assembly.GetEntryAssembly().GetName()} install'.";
                 _log.Fatal(message);

                 ExitCode = (int) TopshelfExitCode.ServiceNotInstalled;
@@ -372,4 +372,4 @@
             public PowerEventCode EventCode { get; }
         }
     }
-}+}


V9/feature/log telemetry level changing (#12299)

* Add logging to SetConsentLevel

* Obsolete old ctor and change logging to email

* Fixed a few issues with MetricsConsentService logging

* Fixed null check

Co-authored-by: Bjarke Berg <1d6e1cf70ec6f9ab28d3ea4b27a49a77654d370e@bergmania.dk>

--- src/Umbraco.Core/Services/MetricsConsentService.cs
+++ src/Umbraco.Core/Services/MetricsConsentService.cs
@@ -1,5 +1,9 @@
 using System;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
 using Umbraco.Cms.Core.Models;
+using Umbraco.Cms.Core.Security;
+using Umbraco.Cms.Web.Common.DependencyInjection;

 namespace Umbraco.Cms.Core.Services
 {
@@ -8,10 +12,27 @@
         internal const string Key = "UmbracoAnalyticsLevel";

         private readonly IKeyValueService _keyValueService;
+        private readonly ILogger<MetricsConsentService> _logger;
+        private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor;

+        // Scheduled for removal in V12
+        [Obsolete("Please use the constructor that takes and ILogger and IBackOfficeSecurity instead")]
         public MetricsConsentService(IKeyValueService keyValueService)
+        : this(
+            keyValueService,
+            StaticServiceProvider.Instance.GetRequiredService<ILogger<MetricsConsentService>>(),
+            StaticServiceProvider.Instance.GetRequiredService<IBackOfficeSecurityAccessor>())
+        {
+        }
+
+        public MetricsConsentService(
+            IKeyValueService keyValueService,
+            ILogger<MetricsConsentService> logger,
+            IBackOfficeSecurityAccessor backOfficeSecurityAccessor)
         {
             _keyValueService = keyValueService;
+            _logger = logger;
+            _backOfficeSecurityAccessor = backOfficeSecurityAccessor;
         }

         public TelemetryLevel GetConsentLevel()
@@ -28,6 +49,8 @@

         public void SetConsentLevel(TelemetryLevel telemetryLevel)
         {
+            var currentUser = _backOfficeSecurityAccessor.BackOfficeSecurity?.CurrentUser;
+            _logger.LogInformation("Telemetry level set to {telemetryLevel} by {username}", telemetryLevel, currentUser?.Username);
             _keyValueService.SetValue(Key, telemetryLevel.ToString());
         }
     }


Fixed tests calling the wrong method

Fixed tests calling the wrong method

--- src/UnitTestProject1/Time/Formats/UnixtimeTests.cs
+++ src/UnitTestProject1/Time/Formats/UnixtimeTests.cs
@@ -1,6 +1,7 @@
 using System;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
 using Skybrud.Essentials.Time;
+using Skybrud.Essentials.Time.UnixTime;

 #pragma warning disable 618

@@ -80,9 +81,12 @@
                 new { Timestamp = 1483384930, Date = new DateTimeOffset(2017, 1, 2, 20, 22, 10, TimeSpan.FromHours(+1)) }
             };

-            foreach (var sample in samples) {
-                Assert.AreEqual(sample.Date, TimeHelper.GetDateTimeFromUnixTime(sample.Timestamp), "\n\n" + sample.Timestamp + " (TimeHelper)");
-                Assert.AreEqual(sample.Date, TimeUtils.GetDateTimeFromUnixTime(sample.Timestamp), "\n\n" + sample.Timestamp + " (TimeUtils)");
+            int n = 1;
+            foreach (var sample in samples) {
+                Assert.AreEqual(sample.Date, TimeHelper.GetDateTimeOffsetFromUnixTime(sample.Timestamp), $"\n\n#{n}. {sample.Timestamp} (TimeHelper)");
+                Assert.AreEqual(sample.Date, TimeUtils.GetDateTimeOffsetFromUnixTime(sample.Timestamp), $"\n\n#{n}. {sample.Timestamp} (TimeUtils)");
+                Assert.AreEqual(sample.Date, UnixTimeUtils.FromSeconds(sample.Timestamp), $"\n\n#{n}. {sample.Timestamp} (UnixTimeUtils)");
+                n++;
             }

         }
@@ -96,9 +100,12 @@
                 new { Timestamp = 1483384930L, Date = new DateTimeOffset(2017, 1, 2, 20, 22, 10, TimeSpan.FromHours(+1)) }
             };

-            foreach (var sample in samples) {
-                Assert.AreEqual(sample.Date, TimeHelper.GetDateTimeFromUnixTime(sample.Timestamp), "\n\n" + sample.Timestamp + " (TimeHelper)");
-                Assert.AreEqual(sample.Date, TimeUtils.GetDateTimeFromUnixTime(sample.Timestamp), "\n\n" + sample.Timestamp + " (TimeUtils)");
+            int n = 1;
+            foreach (var sample in samples) {
+                Assert.AreEqual(sample.Date, TimeHelper.GetDateTimeOffsetFromUnixTime(sample.Timestamp), $"\n\n#{n}. {sample.Timestamp} (TimeHelper)");
+                Assert.AreEqual(sample.Date, TimeUtils.GetDateTimeOffsetFromUnixTime(sample.Timestamp), $"\n\n#{n}. {sample.Timestamp} (TimeUtils)");
+                Assert.AreEqual(sample.Date, UnixTimeUtils.FromSeconds(sample.Timestamp), $"\n\n#{n}. {sample.Timestamp} (UnixTimeUtils)");
+                n++;
             }

         }
@@ -112,9 +119,12 @@
                 new { Timestamp = 1483384930d, Date = new DateTimeOffset(2017, 1, 2, 20, 22, 10, TimeSpan.FromHours(+1)) }
             };

-            foreach (var sample in samples) {
-                Assert.AreEqual(sample.Date, TimeHelper.GetDateTimeFromUnixTime(sample.Timestamp), "\n\n" + sample.Timestamp + " (TimeHelper)");
-                Assert.AreEqual(sample.Date, TimeUtils.GetDateTimeFromUnixTime(sample.Timestamp), "\n\n" + sample.Timestamp + " (TimeUtils)");
+            int n = 1;
+            foreach (var sample in samples) {
+                Assert.AreEqual(sample.Date, TimeHelper.GetDateTimeOffsetFromUnixTime(sample.Timestamp), $"\n\n#{n}. {sample.Timestamp} (TimeHelper)");
+                Assert.AreEqual(sample.Date, TimeUtils.GetDateTimeOffsetFromUnixTime(sample.Timestamp), $"\n\n#{n}. {sample.Timestamp} (TimeUtils)");
+                Assert.AreEqual(sample.Date, UnixTimeUtils.FromSeconds(sample.Timestamp), $"\n\n#{n}. {sample.Timestamp} (UnixTimeUtils)");
+                n++;
             }

         }
@@ -128,9 +138,12 @@
                 new { Timestamp = "1483384930", Date = new DateTimeOffset(2017, 1, 2, 20, 22, 10, TimeSpan.FromHours(+1)) }
             };

-            foreach (var sample in samples) {
-                Assert.AreEqual(sample.Date, TimeHelper.GetDateTimeFromUnixTime(sample.Timestamp), "\n\n" + sample.Timestamp + " (TimeHelper)");
-                Assert.AreEqual(sample.Date, TimeUtils.GetDateTimeFromUnixTime(sample.Timestamp), "\n\n" + sample.Timestamp + " (TimeUtils)");
+            int n = 1;
+            foreach (var sample in samples) {
+                Assert.AreEqual(sample.Date, TimeHelper.GetDateTimeOffsetFromUnixTime(sample.Timestamp), $"\n\n#{n}. {sample.Timestamp} (TimeHelper)");
+                Assert.AreEqual(sample.Date, TimeUtils.GetDateTimeOffsetFromUnixTime(sample.Timestamp), $"\n\n#{n}. {sample.Timestamp} (TimeUtils)");
+                Assert.AreEqual(sample.Date, UnixTimeUtils.FromSeconds(sample.Timestamp), $"\n\n#{n}. {sample.Timestamp} (UnixTimeUtils)");
+                n++;
             }

         }


Fixed invalid comment in function test project.

--- test/Itinero.Optimization.Test.Functional/Program.cs
+++ test/Itinero.Optimization.Test.Functional/Program.cs
@@ -108,7 +108,7 @@
             route = router.CalculateTSPTW(Itinero.Osm.Vehicles.Vehicle.Car.Fastest(), locations, windows, 0, locations.Length - 1);
             route = router.CalculateTSPTW(Itinero.Osm.Vehicles.Vehicle.Car.Fastest(), locations, windows, 0, null);

-            calculate directed TSP - TW.
+            // calculate directed TSP - TW.
             route = router.CalculateTSPTWDirected(Itinero.Osm.Vehicles.Vehicle.Car.Fastest(), locations, windows, 60, 0, 0);
             // TODO: fix or add a solver capable of handling this.
             route = router.CalculateTSPTWDirected(Itinero.Osm.Vehicles.Vehicle.Car.Fastest(), locations, windows, 60, 0, locations.Length - 1);


handle agile board methods as not implemented

--- src/YouTrackSharp/AgileBoards/AgileBoardService.cs
+++ src/YouTrackSharp/AgileBoards/AgileBoardService.cs
@@ -25,6 +25,8 @@
         /// <inheritdoc />
         public async Task<string> CreateAgileBoard(AgileSettings agileSettings)
         {
+            throw new NotImplementedException();
+            /*
             if (agileSettings == null)
             {
                 throw new ArgumentNullException(nameof(agileSettings));
@@ -55,11 +57,14 @@
             var locationHeader = response.Headers.Location.ToString();

             return locationHeader.Substring(locationHeader.IndexOf(marker, StringComparison.OrdinalIgnoreCase) + marker.Length);
+            */
         }

         /// <inheritdoc />
         public async Task<ICollection<AgileSettings>> GetAgileBoards()
         {
+            throw new NotImplementedException();
+            /*
             var client = await _connection.GetAuthenticatedHttpClient();
             var response = await client.GetAsync("rest/admin/agile");

@@ -71,11 +76,14 @@
             response.EnsureSuccessStatusCode();

             return JsonConvert.DeserializeObject<ICollection<AgileSettings>>(await response.Content.ReadAsStringAsync());
+            */
         }

         /// <inheritdoc />
         public async Task<AgileSettings> GetAgileBoard(string agileBoardId)
         {
+            throw new NotImplementedException();
+            /*
             var client = await _connection.GetAuthenticatedHttpClient();
             var response = await client.GetAsync($"rest/admin/agile/{agileBoardId}");

@@ -87,11 +95,14 @@
             response.EnsureSuccessStatusCode();

             return JsonConvert.DeserializeObject<AgileSettings>(await response.Content.ReadAsStringAsync());
+            */
         }

         /// <inheritdoc />
         public async Task UpdateAgileBoard(string agileBoardId, AgileSettings agileSettings)
         {
+            throw new NotImplementedException();
+            /*
             if (agileSettings == null)
             {
                 throw new ArgumentNullException(nameof(agileSettings));
@@ -124,11 +135,14 @@
             }

             response.EnsureSuccessStatusCode();
+            */
         }

         /// <inheritdoc />
         public async Task<Sprint> GetSprint(string agileBoardId, string sprintId)
         {
+            throw new NotImplementedException();
+            /*
             var client = await _connection.GetAuthenticatedHttpClient();
             var response = await client.GetAsync($"rest/admin/agile/{agileBoardId}/sprint/{sprintId}");

@@ -140,6 +154,7 @@
             response.EnsureSuccessStatusCode();

             return JsonConvert.DeserializeObject<Sprint>(await response.Content.ReadAsStringAsync());
+            */
         }
     }
 }


BS push

BS push

--- Derby/Views/Competition/Details.cshtml
+++ Derby/Views/Competition/Details.cshtml
@@ -253,7 +253,7 @@

-                                            Build Race/Heats for Den
+                                            Build Race/Heats for Den-


Fixed load texture in material path.

Fixed load texture in material path.

--- Dev/Editor/EffekseerCore/Utils/Misc.cs
+++ Dev/Editor/EffekseerCore/Utils/Misc.cs
@@ -26,19 +26,23 @@
 		}
 		public static string GetAbsolutePath(string basePath, string path)
 		{
-			Func<string, string> escape = (string s) =>
+			Func<string, string> doubleBackslashToSlash = (string s) =>
 			{
-				return s.Replace("%", "%25");
+				string input = s;
+				string pattern = @"\\";
+				string replacement = @"/";
+				string result = System.Text.RegularExpressions.Regex.Replace(input, pattern, replacement);
+				return result;
 			};

-			Func<string, string> unescape = (string s) =>
-			{
-				return s.Replace("%25", "%");
-			};
-
-			Uri escaped = new Uri(escape(basePath));
-			Uri targetPath = new Uri(escaped, escape(path));
-			return unescape(Uri.UnescapeDataString(targetPath.LocalPath));
+			var basePath_ecs = new Uri(basePath, UriKind.Relative);
+			var path_ecs = new Uri(path, UriKind.Relative);
+			var basePath_slash = doubleBackslashToSlash(basePath_ecs.ToString());
+			var basePath_uri = new Uri(basePath_slash, UriKind.Absolute);
+			var path_uri = new Uri(path_ecs.ToString(), UriKind.Relative);
+			var targetPath = new Uri(basePath_uri, path_uri);
+			var ret = targetPath.LocalPath.ToString();
+			return ret;
 		}
 	}
 }


catch auth exception from OriginalCompleted

Just catching the Exception in OriginalCompleted is
enought to prevent VS crash.

Does not handle the exception just swollows it.

--- src/GitHub.App/ViewModels/PullRequestListViewModel.cs
+++ src/GitHub.App/ViewModels/PullRequestListViewModel.cs
@@ -108,6 +108,10 @@

             pullRequests.OriginalCompleted
                 .ObserveOn(RxApp.MainThreadScheduler)
+                .Catch<System.Reactive.Unit, Octokit.AuthorizationException>(ex => {
+                    //TODO handle the auth exception here
+                    return Observable.Empty<System.Reactive.Unit>();
+                })
                 .Subscribe(_ =>
                 {
                     if (listSettings.SelectedAuthor != null)


Fixed the spelling of the "delayed" queue

--- src/Jasper/Bus/Delayed/InMemoryDelayedJobProcessor.cs
+++ src/Jasper/Bus/Delayed/InMemoryDelayedJobProcessor.cs
@@ -11,7 +11,7 @@
 {
     public class InMemoryDelayedJobProcessor : IDelayedJobProcessor, IDisposable
     {
-        public static readonly Uri Queue = "memory://delated".ToUri();
+        public static readonly Uri Queue = "memory://delayed".ToUri();

         public static InMemoryDelayedJobProcessor ForSender(ISender sender)
         {


Added csrf validation

Added csrf validation

--- src/JoyOI.UserCenter/Controllers/AccountController.cs
+++ src/JoyOI.UserCenter/Controllers/AccountController.cs
@@ -25,6 +25,16 @@
         private static Regex usernameRegex = new Regex("^(" + usernameRegexString + ")$");
         private static MD5 _md5 = MD5.Create();

+        [NonAction]
+        private IActionResult _Prompt(Action<Prompt> setupPrompt)
+        {
+            var prompt = new Prompt();
+            setupPrompt(prompt);
+            Response.StatusCode = prompt.StatusCode;
+            return View("_Prompt", prompt);
+        }
+
+
         [HttpGet("[controller]/{id:Guid?}")]
         public async Task<IActionResult> Index(Guid? userId)
         {
@@ -59,6 +69,7 @@
         }

         [HttpPost]
+        [ValidateAntiForgeryToken]
         public async Task<IActionResult> Login(string username, string password)
         {
             var users = DB.Users
@@ -95,6 +106,7 @@
         }

         [HttpPost]
+        [ValidateAntiForgeryToken]
         public IActionResult Profile(Guid id, string nickName, string school, Sex sex, AvatarSource avatarSource, IFormFile avatar, string gravatar)
         {
             var user = DB.Users.SingleOrDefault(x => x.Id == id);
@@ -150,6 +162,8 @@
             });
         }

+        [HttpPost]
+        [ValidateAntiForgeryToken]
         public async Task<IActionResult> Password(Guid id, string oldPassword, string newPassword, string confirm, string role)
         {
             var user = DB.Users.SingleOrDefault(x => x.Id == id);
@@ -205,15 +219,6 @@
                 x.Title = SR["Password Updated"];
                 x.Details = SR["The new password is active now."];
             });
-        }
-
-        [NonAction]
-        private IActionResult _Prompt(Action<Prompt> setupPrompt)
-        {
-            var prompt = new Prompt();
-            setupPrompt(prompt);
-            Response.StatusCode = prompt.StatusCode;
-            return View("_Prompt", prompt);
         }

         [HttpGet("/Register")]
@@ -306,6 +311,7 @@
         }

         [HttpPost("/Register/VerifyEmail")]
+        [ValidateAntiForgeryToken]
         public async Task<IActionResult> VerifyEmail(
             string email,
             string username,


fix(#107): EF bug

fix(#107): EF bug

tracking: https://github.com/aspnet/EntityFramework/issues/8462

--- src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
+++ src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
@@ -85,9 +85,12 @@

         public virtual async Task<TEntity> GetAndIncludeAsync(TId id, string relationshipName)
         {
-            return await Get()
+            var result = await Get()
                 .Include(relationshipName)
-                .SingleOrDefaultAsync(e => e.Id.Equals(id));
+                .Where(e => e.Id.Equals(id))
+                .ToListAsync();
+
+            return result.SingleOrDefault();
         }

         public virtual async Task<TEntity> CreateAsync(TEntity entity)


not showin enter when user is comming back. This closes #76

--- src/Kondor.Service/Handlers/TelegramMessageHandler.cs
+++ src/Kondor.Service/Handlers/TelegramMessageHandler.cs
@@ -221,11 +221,8 @@
                         {
                         new[]
                         {
-                            new InlineKeyboardButton
-                            {
-                                Text = _textManager.GetText(StringResources.KeyboardEnterTitle),
-                                CallbackData = QueryData.NewQueryString("Enter", null, null)
-                            }
+                            new InlineKeyboardButton {Text = _textManager.GetText(StringResources.KeyboardLearnTitle), CallbackData = QueryData.NewQueryString("Learn", null, null)},
+                            new InlineKeyboardButton {Text = _textManager.GetText(StringResources.KeyboardExamTitle), CallbackData = QueryData.NewQueryString("Exam", null, null)}
                         }
                         }));
                 }


Fix sorting of linked accounts

Fix sorting of linked accounts

Also sort by the provider key if there is no display name set.

--- src/LondonTravel.Site/Controllers/ManageController.cs
+++ src/LondonTravel.Site/Controllers/ManageController.cs
@@ -66,6 +66,7 @@
             var userLogins = (await _userManager.GetLoginsAsync(user))
                 .OrderBy((p) => p.ProviderDisplayName)
                 .ThenBy((p) => p.LoginProvider)
+                .ThenBy((p) => p.ProviderKey)
                 .ToList();

             var otherLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync())


The DefaultKeyValueStore now creates a message bus in correct format.

--- src/Main/Hadouken.Impl/Config/DefaultKeyValueStore.cs
+++ src/Main/Hadouken.Impl/Config/DefaultKeyValueStore.cs
@@ -27,7 +27,7 @@
         public DefaultKeyValueStore(IDataRepository data, IMessageBusFactory busFactory)
         {
             _data = data;
-            _bus = busFactory.Create("hdkn_keyvaluestore");
+            _bus = busFactory.Create("hdkn.keyValueStore");
         }

         public object Get(string key)


Make the implementation method private.

Make the implementation method private.

--- src/Edulinq/Repeat.cs
+++ src/Edulinq/Repeat.cs
@@ -29,7 +29,7 @@
             return RepeatImpl(element, count);
         }

-        public static IEnumerable<TResult> RepeatImpl<TResult>(TResult element, int count)
+        private static IEnumerable<TResult> RepeatImpl<TResult>(TResult element, int count)
         {
             for (int i = 0; i < count; i++)
             {


Use curly brace blocks.

Use curly brace blocks.

--- src/MitternachtBot/Services/Impl/BotConfigProvider.cs
+++ src/MitternachtBot/Services/Impl/BotConfigProvider.cs
@@ -28,16 +28,20 @@
 			var bc = uow.BotConfig.GetOrCreate();
 			switch(type) {
 				case BotConfigEditType.CurrencyGenerationChance:
-					if(float.TryParse(newValue, out var chance) && chance >= 0 && chance <= 1)
+					if(float.TryParse(newValue, out var chance) && chance >= 0 && chance <= 1) {
 						bc.CurrencyGenerationChance = chance;
-					else
+					} else {
 						return false;
+					}
+
 					break;
 				case BotConfigEditType.CurrencyGenerationCooldown:
-					if(int.TryParse(newValue, out var cd) && cd >= 1)
+					if(int.TryParse(newValue, out var cd) && cd >= 1) {
 						bc.CurrencyGenerationCooldown = cd;
-					else
+					} else {
 						return false;
+					}
+
 					break;
 				case BotConfigEditType.CurrencyName:
 					bc.CurrencyName = newValue ?? "-";
@@ -55,60 +59,78 @@
 					bc.HelpString = string.IsNullOrWhiteSpace(newValue) ? "-" : newValue;
 					break;
 				case BotConfigEditType.CurrencyDropAmount:
-					if(int.TryParse(newValue, out var amount) && amount > 0)
+					if(int.TryParse(newValue, out var amount) && amount > 0) {
 						bc.CurrencyDropAmount = amount;
-					else
+					} else {
 						return false;
+					}
+
 					break;
 				case BotConfigEditType.CurrencyDropAmountMax:
-					if(newValue == null)
+					if(newValue == null) {
 						bc.CurrencyDropAmountMax = null;
-					else if(int.TryParse(newValue, out var maxAmount) && maxAmount > 0)
+					} else if(int.TryParse(newValue, out var maxAmount) && maxAmount > 0) {
 						bc.CurrencyDropAmountMax = maxAmount;
-					else
+					} else {
 						return false;
+					}
+
 					break;
 				case BotConfigEditType.MinimumBetAmount:
-					if(int.TryParse(newValue, out var minBetAmount) && minBetAmount > 0)
+					if(int.TryParse(newValue, out var minBetAmount) && minBetAmount > 0) {
 						bc.MinimumBetAmount = minBetAmount;
-					else
+					} else {
 						return false;
+					}
+
 					break;
 				case BotConfigEditType.Betroll100Multiplier:
-					if(float.TryParse(newValue, out var br100) && br100 > 0)
+					if(float.TryParse(newValue, out var br100) && br100 > 0) {
 						bc.Betroll100Multiplier = br100;
-					else
+					} else {
 						return false;
+					}
+
 					break;
 				case BotConfigEditType.Betroll91Multiplier:
-					if(int.TryParse(newValue, out var br91) && br91 > 0)
+					if(int.TryParse(newValue, out var br91) && br91 > 0) {
 						bc.Betroll91Multiplier = br91;
-					else
+					} else {
 						return false;
+					}
+
 					break;
 				case BotConfigEditType.Betroll67Multiplier:
-					if(int.TryParse(newValue, out var br67) && br67 > 0)
+					if(int.TryParse(newValue, out var br67) && br67 > 0) {
 						bc.Betroll67Multiplier = br67;
-					else
+					} else {
 						return false;
+					}
+
 					break;
 				case BotConfigEditType.BetflipMultiplier:
-					if(int.TryParse(newValue, out var bf) && bf > 0)
+					if(int.TryParse(newValue, out var bf) && bf > 0) {
 						bc.BetflipMultiplier = bf;
-					else
+					} else {
 						return false;
+					}
+
 					break;
 				case BotConfigEditType.HereChance:
-					if(double.TryParse(newValue, NumberStyles.Float, CultureInfo.InvariantCulture.NumberFormat, out var evchance) && evchance > 0)
+					if(double.TryParse(newValue, NumberStyles.Float, CultureInfo.InvariantCulture.NumberFormat, out var evchance) && evchance > 0) {
 						bc.FirstAprilHereChance = evchance;
-					else
+					} else {
 						return false;
+					}
+
 					break;
 				case BotConfigEditType.DmCommandsOwnerOnly:
-					if(bool.TryParse(newValue, out var owneronly))
+					if(bool.TryParse(newValue, out var owneronly)) {
 						bc.DmCommandsOwnerOnly = owneronly;
-					else
+					} else {
 						return false;
+					}
+
 					break;
 				default:
 					return false;
@@ -118,7 +140,7 @@
 			uow.SaveChanges();

 			BotConfigChanged?.Invoke(BotConfig);
-
+
 			return true;
 		}
 	}


Fix NH-1661

Fix NH-1661

SVN: 488784591515bd4cdaa016be4ec9b172dc4e7caf@4064

--- src/NHibernate/Connection/DriverConnectionProvider.cs
+++ src/NHibernate/Connection/DriverConnectionProvider.cs
@@ -10,13 +10,6 @@
 	public class DriverConnectionProvider : ConnectionProvider
 	{
 		private static readonly ILog log = LogManager.GetLogger(typeof(DriverConnectionProvider));
-
-		/// <summary>
-		/// Initializes a new instance of the <see cref="DriverConnectionProvider"/> class.
-		/// </summary>
-		public DriverConnectionProvider()
-		{
-		}

 		/// <summary>
 		/// Closes and Disposes of the <see cref="IDbConnection"/>.
@@ -42,8 +35,17 @@
 		{
 			log.Debug("Obtaining IDbConnection from Driver");
 			IDbConnection conn = Driver.CreateConnection();
-			conn.ConnectionString = ConnectionString;
-			conn.Open();
+			try
+			{
+				conn.ConnectionString = ConnectionString;
+				conn.Open();
+			}
+			catch (Exception)
+			{
+				conn.Dispose();
+				throw;
+			}
+
 			return conn;
 		}
 	}


Fix XML comment

Fix XML comment

SVN: 488784591515bd4cdaa016be4ec9b172dc4e7caf@2624

--- src/NHibernate/Connection/DriverConnectionProvider.cs
+++ src/NHibernate/Connection/DriverConnectionProvider.cs
@@ -35,7 +35,7 @@
 		/// <returns>
 		/// An Open <see cref="IDbConnection"/>.
 		/// </returns>
-		/// <exception>
+		/// <exception cref="Exception">
 		/// If there is any problem creating or opening the <see cref="IDbConnection"/>.
 		/// </exception>
 		public override IDbConnection GetConnection()


Fixes for dialogs on mobile/tablet-mode.

--- src/Neptunium/Core/UI/NepAppUIManagerOverlayHandle.cs
+++ src/Neptunium/Core/UI/NepAppUIManagerOverlayHandle.cs
@@ -7,6 +7,7 @@
 using Windows.Foundation;
 using Windows.UI;
 using Windows.UI.Core;
+using Windows.UI.ViewManagement;
 using Windows.UI.Xaml;
 using Windows.UI.Xaml.Controls;
 using Windows.UI.Xaml.Input;
@@ -38,6 +39,7 @@
             inlineFrame.ContentTransitions.Add(new ContentThemeTransition());

             //todo handle orientation, etc
+            ApplicationView.GetForCurrentView().VisibleBoundsChanged += NepAppUIManagerOverlayHandle_VisibleBoundsChanged;
             Window.Current.SizeChanged += Current_SizeChanged;
             Rect bounds = GetScreenBounds();
             ResizeInlineFrameDialog(bounds.Height, bounds.Width);
@@ -54,15 +56,18 @@
             overlayGridControl.Transitions.Add(new PaneThemeTransition());
         }

+        private void NepAppUIManagerOverlayHandle_VisibleBoundsChanged(ApplicationView sender, object args)
+        {
+            var visibleScreen = GetScreenBounds();
+            ResizeInlineFrameDialog(visibleScreen.Height, visibleScreen.Width);
+        }
+
         private Rect GetScreenBounds()
         {
-            //todo check if table mode counts. i forgot.
-            if (Crystal3.CrystalApplication.GetDevicePlatform() == Crystal3.Core.Platform.Mobile)
+            if (Crystal3.CrystalApplication.GetDevicePlatform() == Crystal3.Core.Platform.Mobile
+                || UIViewSettings.GetForCurrentView().UserInteractionMode == UserInteractionMode.Touch)
             {
-                if (AreOnScreenNavigationButtonsVisibleOnMobile())
-                {
-                    return Windows.UI.ViewManagement.ApplicationView.GetForCurrentView().VisibleBounds;
-                }
+                return Windows.UI.ViewManagement.ApplicationView.GetForCurrentView().VisibleBounds;
             }

             return Window.Current.Bounds;
@@ -80,7 +85,6 @@
         {
             var visibleScreen = GetScreenBounds();
             ResizeInlineFrameDialog(visibleScreen.Height, visibleScreen.Width);
-
         }

         private void ResizeInlineFrameDialog(double height, double width)
@@ -93,8 +97,8 @@
             else
             {
                 inlineFrame.Width = width;
-                inlineFrame.Height = height;
-
+                inlineFrame.Height = height - 20;
+
             }
         }


Handle on screen navigation buttons on dialogs.

--- src/Neptunium/Core/UI/NepAppUIManagerOverlayHandle.cs
+++ src/Neptunium/Core/UI/NepAppUIManagerOverlayHandle.cs
@@ -4,6 +4,7 @@
 using System.ComponentModel;
 using System.Threading;
 using System.Threading.Tasks;
+using Windows.Foundation;
 using Windows.UI;
 using Windows.UI.Xaml;
 using Windows.UI.Xaml.Controls;
@@ -31,7 +32,8 @@

             //todo handle orientation, etc
             Window.Current.SizeChanged += Current_SizeChanged;
-            ResizeInlineFrameDialog(Window.Current.Bounds.Height, Window.Current.Bounds.Width);
+            Rect bounds = GetScreenBounds();
+            ResizeInlineFrameDialog(bounds.Height, bounds.Width);

             overlayGridControl.Children.Add(inlineFrame);

@@ -41,9 +43,33 @@
             overlayGridControl.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
         }

+        private Rect GetScreenBounds()
+        {
+            //todo check if table mode counts. i forgot.
+            if (Crystal3.CrystalApplication.GetDevicePlatform() == Crystal3.Core.Platform.Mobile)
+            {
+                if (AreOnScreenNavigationButtonsVisibleOnMobile())
+                {
+                    return Windows.UI.ViewManagement.ApplicationView.GetForCurrentView().VisibleBounds;
+                }
+            }
+
+            return Window.Current.Bounds;
+        }
+
+        private bool AreOnScreenNavigationButtonsVisibleOnMobile()
+        {
+            //https://social.msdn.microsoft.com/Forums/sqlserver/en-US/dd050898-ef62-4dec-aac4-32a05142931e/on-screen-software-buttons?forum=wpdevelop
+            var visible = Windows.UI.ViewManagement.ApplicationView.GetForCurrentView().VisibleBounds;
+            var window = Window.Current.Bounds;
+            return (visible.Height != window.Height || visible.Width != window.Width);
+        }
+
         private void Current_SizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)
         {
-            ResizeInlineFrameDialog(e.Size.Height, e.Size.Width);
+            var visibleScreen = GetScreenBounds();
+            ResizeInlineFrameDialog(visibleScreen.Height, visibleScreen.Width);
+
         }

         private void ResizeInlineFrameDialog(double height, double width)
@@ -57,6 +83,7 @@
             {
                 inlineFrame.Width = width;
                 inlineFrame.Height = height;
+
             }
         }


Set up more appropriate build and turn angles

--- Initializer.cs
+++ Initializer.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Linq;
 using UnityEngine;
 using MetroOverhaul.SetupPrefab;
 using SubwayOverhaul.NEXT;
@@ -77,15 +78,17 @@
                 }
                 prefab.m_class.hideFlags = HideFlags.None;
                 prefab.m_class.name = prefab.name;
-                prefab.m_maxBuildAngle = metroTunnel.m_maxBuildAngle;
-                prefab.m_maxBuildAngleCos = metroTunnel.m_maxBuildAngleCos;
-                prefab.m_maxTurnAngle = metroTunnel.m_maxTurnAngle;
-                prefab.m_maxTurnAngleCos = metroTunnel.m_maxTurnAngleCos;
+                prefab.m_maxBuildAngle = 90;
+                prefab.m_maxTurnAngleCos = Mathf.Cos(prefab.m_maxBuildAngle);
+                prefab.m_maxTurnAngle = 60;
+                prefab.m_maxTurnAngleCos = Mathf.Cos(prefab.m_maxTurnAngle);
                 prefab.m_averageVehicleLaneSpeed = metroTunnel.m_averageVehicleLaneSpeed;
                 prefab.m_UnlockMilestone = metroTunnel.m_UnlockMilestone;
                 prefab.m_createGravel = false;
                 prefab.m_createPavement = true;
                 prefab.m_halfWidth = 5;
+
+                var speedLimit = metroTunnel.m_lanes.First(l => l.m_vehicleType != VehicleInfo.VehicleType.None).m_speedLimit;

                 foreach (var lane in prefab.m_lanes)
                 {
@@ -96,6 +99,7 @@
                     else
                     {
                         lane.m_vehicleType = VehicleInfo.VehicleType.Metro;
+                        lane.m_speedLimit = speedLimit;
                     }
                 }


search page modified

search page modified

--- Dotchi/Dotchi/Views/Home/Search.cshtml
+++ Dotchi/Dotchi/Views/Home/Search.cshtml
@@ -14,13 +14,21 @@
 			FB登入

-

-
<input type="text" value="@(ViewBag.QueryString)">

-            找餐廳
-

-

+

+

+                @foreach(var tagItem in RecommendTagList)
+                {
+

+
+                            @(tagItem.Name)
+                            @(tagItem.Number)
+
+

+                }
+

+

         @foreach (var shopItem in ShopList)
         {

@@ -58,18 +66,5 @@

         }
-

-

-                @foreach(var tagItem in RecommendTagList)
-                {
-

-
-                            @(tagItem.Name)
-                            @(tagItem.Number)
-
-

-                }
-

-


Changed unittest to use individual logs to avoid sharingviolations when running tests back-to-back

--- Duplicati/UnitTest/SVNCheckoutsTest.cs
+++ Duplicati/UnitTest/SVNCheckoutsTest.cs
@@ -74,8 +74,8 @@
         /// <param name="target">The target destination for the backups</param>
         public static void RunTest(string[] folders, Dictionary<string, string> options, string target)
         {
-            LogHelper log = new LogHelper("unittest.log");
-            Log.CurrentLog = log; ;
+            LogHelper log = new LogHelper("unittest-{0}.log", Library.Utility.Utility.SerializeDateTime(DateTime.Now));
+            Log.CurrentLog = log;
             Log.LogLevel = Duplicati.Library.Logging.LogMessageType.Profiling;

             string tempdir = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "tempdir");


8.3.3

--- EDDiscovery/Properties/AssemblyInfo.cs
+++ EDDiscovery/Properties/AssemblyInfo.cs
@@ -47,6 +47,6 @@
 // You can specify all the values or you can default the Build and Revision Numbers
 // by using the '*' as shown below:
 // [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("8.3.2.0")]
-[assembly: AssemblyFileVersion("8.3.2.0")]
+[assembly: AssemblyVersion("8.3.3.0")]
+[assembly: AssemblyFileVersion("8.3.3.0")]


8.4.0

--- EDDiscovery/Properties/AssemblyInfo.cs
+++ EDDiscovery/Properties/AssemblyInfo.cs
@@ -47,6 +47,6 @@
 // You can specify all the values or you can default the Build and Revision Numbers
 // by using the '*' as shown below:
 // [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("8.3.3.0")]
-[assembly: AssemblyFileVersion("8.3.3.0")]
+[assembly: AssemblyVersion("8.4.0.0")]
+[assembly: AssemblyFileVersion("8.4.0.0")]


minor fixes to supplementary session id struct

--- Echo.Process/SupplementarySessionId.cs
+++ Echo.Process/SupplementarySessionId.cs
@@ -66,8 +66,8 @@
         public int CompareTo(object obj) =>
             obj == null
                 ? -1
-                : obj is SupplementarySessionId
-                    ? CompareTo((SupplementarySessionId)obj)
+                : obj is SupplementarySessionId sid
+                    ? CompareTo(sid)
                     : -1;

         public static bool operator == (SupplementarySessionId lhs, SupplementarySessionId rhs) =>
@@ -77,8 +77,6 @@
             !lhs.Equals(rhs);

         public override bool Equals(object obj) =>
-            obj is SupplementarySessionId
-                ? Equals((SupplementarySessionId)obj)
-                : false;
+            obj is SupplementarySessionId sid && Equals(sid);
     }
 }


Allow null self in ArrayFromSingle

Allow null self in ArrayFromSingle

--- Eleven41.Extensions/ArrayExtensions.cs
+++ Eleven41.Extensions/ArrayExtensions.cs
@@ -78,6 +78,9 @@
 		// Create a single-element array from the object.
 		public static T[] ArrayFromSingle<T>(this T self)
 		{
+			if (self == null)
+				return null;
+
 			T[] results = new T[1];
 			results[0] = self;
 			return results;


undo debug code

undo debug code

--- EngineLayer/Indexing/IndexingEngine.cs
+++ EngineLayer/Indexing/IndexingEngine.cs
@@ -68,7 +68,7 @@
             // digest database
             List<PeptideWithSetModifications> globalPeptides = new List<PeptideWithSetModifications>();

-            Parallel.ForEach(Partitioner.Create(0, ProteinList.Count), new ParallelOptions { MaxDegreeOfParallelism = 1 }, (range, loopState) =>
+            Parallel.ForEach(Partitioner.Create(0, ProteinList.Count), new ParallelOptions { MaxDegreeOfParallelism = commonParameters.MaxThreadsToUsePerFile }, (range, loopState) =>
             {
                 List<PeptideWithSetModifications> localPeptides = new List<PeptideWithSetModifications>();


EntityBehaviour Init() is now overridable

--- Entities/Components/EntityBehaviour.cs
+++ Entities/Components/EntityBehaviour.cs
@@ -86,7 +86,7 @@
         /// <summary>
         /// Called when the component is initialized
         /// </summary>
-        public void Init()
+        public virtual void Init()
         {

         }


Upped the version number we're testing for

--- src/tests/Tests/NoticeComponentsCreation.cs
+++ src/tests/Tests/NoticeComponentsCreation.cs
@@ -135,7 +135,7 @@
             AirbrakeNotifier notifier = this.builder.Notifier;
             Assert.That(notifier.Name, Is.EqualTo("SharpBrake"));
             Assert.That(notifier.Url, Is.EqualTo("https://github.com/asbjornu/SharpBrake"));
-            Assert.That(notifier.Version, Is.EqualTo("2.2.0.0"));
+            Assert.That(notifier.Version, Is.EqualTo("2.2.1.0"));
         }


Minor fix to Endpoint URL

Minor fix to Endpoint URL

--- Eurofurence.Companion/Common/Consts.cs
+++ Eurofurence.Companion/Common/Consts.cs
@@ -2,6 +2,6 @@
 {
     public class Consts
     {
-        public const string WEB_API_ENDPOINT_URL = "https://app.eurofurence.org/api/";
+        public const string WEB_API_ENDPOINT_URL = "https://app.eurofurence.org/api";
     }
 }


GremlinQuery: Implement all interface method explicitly.

--- ExRam.Gremlinq/Gremlin/GremlinQuery.cs
+++ ExRam.Gremlinq/Gremlin/GremlinQuery.cs
@@ -20,33 +20,31 @@
             this.StepLabelMappings = stepLabelBindings;
         }

-        public IGremlinQuery<TVertex> AddV<TVertex>(TVertex vertex)
+        IGremlinQuery<TVertex> IGremlinQuery.AddV<TVertex>(TVertex vertex)
         {
             return this
                 .AddStep<TVertex>(new AddVGremlinStep(vertex))
                 .AddStep(new AddElementPropertiesStep(vertex));
         }

-        public IGremlinQuery<TVertex> AddV<TVertex>()
-            where TVertex : new()
-        {
-            return this.AddV(new TVertex());
-        }
-
-        public IGremlinQuery<TEdge> AddE<TEdge>()
-            where TEdge : new()
-        {
-            return this.AddE(new TEdge());
-        }
-
-        public IGremlinQuery<TEdge> AddE<TEdge>(TEdge edge)
+        IGremlinQuery<TVertex> IGremlinQuery.AddV<TVertex>()
+        {
+            return ((IGremlinQuery<TElement>)this).AddV(new TVertex());
+        }
+
+        public IGremlinQuery<TEdge> AddE<TEdge>() where TEdge : new()
+        {
+            return ((IGremlinQuery<TElement>)this).AddE(new TEdge());
+        }
+
+        IGremlinQuery<TEdge> IGremlinQuery.AddE<TEdge>(TEdge edge)
         {
             return this
                 .AddStep<TEdge>(new AddEGremlinStep(edge))
                 .AddStep(new AddElementPropertiesStep(edge));
         }

-        public IGremlinQuery<TElement> And(params Func<IGremlinQuery<TElement>, IGremlinQuery>[] andTraversals)
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.And(params Func<IGremlinQuery<TElement>, IGremlinQuery>[] andTraversals)
         {
             return this.Call(
                 "and",
@@ -59,33 +57,28 @@
                             : list.Add(query2)));
         }

-        public IGremlinQuery<TTarget> As<TTarget>(Func<IGremlinQuery<TElement>, StepLabel<TElement>, IGremlinQuery<TTarget>> continuation)
+        IGremlinQuery<TTarget> IGremlinQuery<TElement>.As<TTarget>(Func<IGremlinQuery<TElement>, StepLabel<TElement>, IGremlinQuery<TTarget>> continuation)
         {
             var stepLabel = new StepLabel<TElement>();

             return continuation(
-                this.As(stepLabel),
+                ((IGremlinQuery<TElement>)this).As(stepLabel),
                 stepLabel);
         }

-        public IGremlinQuery<TElement> As(StepLabel<TElement> stepLabel)
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.As(StepLabel<TElement> stepLabel)
         {
             return this
                 .Call("as", stepLabel);
         }

-        public IGremlinQuery<TElement> Barrier()
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.Barrier()
         {
             return this
                 .Call("barrier");
         }

         IGremlinQuery<TTarget> IGremlinQuery.Cast<TTarget>()
-        {
-            return this.Cast<TTarget>();
-        }
-
-        public IGremlinQuery<TTarget> Cast<TTarget>()
         {
             return new GremlinQueryImpl<TTarget>(this.Steps, this.StepLabelMappings);
         }
@@ -100,7 +93,7 @@
         //    return new GremlinQueryImpl<TOutVertex, TTarget, TElement>(this.Steps, this.StepLabelMappings);
         //}

-        public IGremlinQuery<TTarget> Coalesce<TTarget>(params Func<IGremlinQuery<TElement>, IGremlinQuery<TTarget>>[] traversals)
+        IGremlinQuery<TTarget> IGremlinQuery<TElement>.Coalesce<TTarget>(params Func<IGremlinQuery<TElement>, IGremlinQuery<TTarget>>[] traversals)
         {
             return this
                 .Call<TTarget>(
@@ -110,7 +103,7 @@
                         .ToImmutableList<object>());
         }

-        public IGremlinQuery<TResult> Choose<TResult>(Func<IGremlinQuery<TElement>, IGremlinQuery> traversalPredicate, Func<IGremlinQuery<TElement>, IGremlinQuery<TResult>> trueChoice, Func<IGremlinQuery<TElement>, IGremlinQuery<TResult>> falseChoice)
+        IGremlinQuery<TResult> IGremlinQuery<TElement>.Choose<TResult>(Func<IGremlinQuery<TElement>, IGremlinQuery> traversalPredicate, Func<IGremlinQuery<TElement>, IGremlinQuery<TResult>> trueChoice, Func<IGremlinQuery<TElement>, IGremlinQuery<TResult>> falseChoice)
         {
             var anonymous = this.ToAnonymous();

@@ -122,7 +115,7 @@
                     falseChoice(anonymous));
         }

-        public IGremlinQuery<TResult> Choose<TResult>(Func<IGremlinQuery<TElement>, IGremlinQuery> traversalPredicate, Func<IGremlinQuery<TElement>, IGremlinQuery<TResult>> trueChoice)
+        IGremlinQuery<TResult> IGremlinQuery<TElement>.Choose<TResult>(Func<IGremlinQuery<TElement>, IGremlinQuery> traversalPredicate, Func<IGremlinQuery<TElement>, IGremlinQuery<TResult>> trueChoice)
         {
             var anonymous = this.ToAnonymous();

@@ -133,31 +126,31 @@
                     trueChoice(anonymous));
         }

-        public IGremlinQuery<Vertex> Both()
+        IGremlinQuery<Vertex> IGremlinQuery.Both()
         {
             return this
                 .AddStep<Vertex>(new DerivedLabelNamesGremlinStep<TElement>("both"));
         }

-        public IGremlinQuery<TEdge> BothE<TEdge>()
+        IGremlinQuery<TEdge> IGremlinQuery.BothE<TEdge>()
         {
             return this
                 .AddStep<TEdge>(new DerivedLabelNamesGremlinStep<TEdge>("bothE"));
         }

-        public IGremlinQuery<Vertex> BothV()
+        IGremlinQuery<Vertex> IGremlinQuery.BothV()
         {
             return this
                 .Call<Vertex>("bothV");
         }

-        public IGremlinQuery<TEnd> BranchOnIdentity<TEnd>(params Func<IGremlinQuery<TElement>, IGremlinQuery<TEnd>>[] options)
-        {
-            return this
+        IGremlinQuery<TEnd> IGremlinQuery<TElement>.BranchOnIdentity<TEnd>(params Func<IGremlinQuery<TElement>, IGremlinQuery<TEnd>>[] options)
+        {
+            return ((IGremlinQuery<TElement>)this)
                 .Branch(_ => _.Identity(), options);
         }

-        public IGremlinQuery<TEnd> Branch<TBranch, TEnd>(Func<IGremlinQuery<TElement>, IGremlinQuery<TBranch>> branchSelector, params Func<IGremlinQuery<TBranch>, IGremlinQuery<TEnd>>[] options)
+        IGremlinQuery<TEnd> IGremlinQuery<TElement>.Branch<TBranch, TEnd>(Func<IGremlinQuery<TElement>, IGremlinQuery<TBranch>> branchSelector, params Func<IGremlinQuery<TBranch>, IGremlinQuery<TEnd>>[] options)
         {
             return options
                 .Aggregate(
@@ -167,13 +160,13 @@
                 .Cast<TEnd>();
         }

-        public IGremlinQuery<TElement> ByTraversal(Func<IGremlinQuery<TElement>, IGremlinQuery> traversal, Order sortOrder)
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.ByTraversal(Func<IGremlinQuery<TElement>, IGremlinQuery> traversal, Order sortOrder)
         {
             return this
                 .Call("by", traversal(this.ToAnonymous()), sortOrder);
         }

-        public IGremlinQuery<TElement> ByMember(Expression<Func<TElement, object>> projection, Order sortOrder)
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.ByMember(Expression<Func<TElement, object>> projection, Order sortOrder)
         {
             var body = projection.Body;
             if (body is UnaryExpression && body.NodeType == ExpressionType.Convert)
@@ -188,79 +181,79 @@
             throw new NotSupportedException();
         }

-        public IGremlinQuery<TElement> ByLambda(string lambdaString)
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.ByLambda(string lambdaString)
         {
             return this
                 .Call("by", new Lambda(lambdaString));
         }

-        public IGremlinQuery<TElement> Dedup()
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.Dedup()
         {
             return this
                 .Call("dedup");
         }

-        public IGremlinQuery<Unit> Drop()
+        IGremlinQuery<Unit> IGremlinQuery.Drop()
         {
             return this
                 .Call<Unit>("drop");
         }

-        public IGremlinQuery<Edge> E(params object[] ids)
+        IGremlinQuery<Edge> IGremlinQuery.E(params object[] ids)
         {
             return this
                 .Call<Edge>("E", ids);
         }

-        public IGremlinQuery<TElement> Emit()
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.Emit()
         {
             return this
                 .Call("emit");
         }

-        public IGremlinQuery<TElement> Explain()
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.Explain()
         {
             return this
                 .Call("explain");
         }

-        public IGremlinQuery<TElement> FilterWithLambda(string lambda)
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.FilterWithLambda(string lambda)
         {
             return this
                 .Call("filter", new Lambda(lambda));
         }

-        public IGremlinQuery<TElement[]> Fold()
+        IGremlinQuery<TElement[]> IGremlinQuery<TElement>.Fold()
         {
             return this
                 .Call<TElement[]>("fold");
         }

-        public IGremlinQuery<TElement> From<TStepLabel>(StepLabel<TStepLabel> stepLabel)
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.From<TStepLabel>(StepLabel<TStepLabel> stepLabel)
         {
             return this
                 .Call("from", stepLabel);
         }

-        public IGremlinQuery<TElement> From(Func<IGremlinQuery<TElement>, IGremlinQuery> fromVertex)
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.From(Func<IGremlinQuery<TElement>, IGremlinQuery> fromVertex)
         {
             return this
                 .Call("from", fromVertex(this.ToAnonymous()));
         }

-        public IGremlinQuery<object> Id()
+        IGremlinQuery<object> IGremlinQuery.Id()
         {
             return this
                 .Call<object>("id");
         }

-        public IGremlinQuery<TElement> Identity()
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.Identity()
         {
             return this
                 .Call("identity");
         }

-        public IGremlinQuery<Vertex> In<TEdge>()
+        IGremlinQuery<Vertex> IGremlinQuery.In<TEdge>()
         {
             return this
                 .AddStep<Vertex>(new DerivedLabelNamesGremlinStep<TEdge>("in"));
@@ -268,77 +261,72 @@

         IGremlinQuery<TTarget> IGremlinQuery.InsertStep<TTarget>(int index, GremlinStep step)
         {
-            return this.InsertStep<TTarget>(index, step);
-        }
-
-        public IGremlinQuery<TTarget> InsertStep<TTarget>(int index, GremlinStep step)
-        {
             return new GremlinQueryImpl<TTarget>(this.Steps.Insert(index, step), this.StepLabelMappings);
         }

-        public IGremlinQuery<TEdge> InE<TEdge>()
+        IGremlinQuery<TEdge> IGremlinQuery.InE<TEdge>()
         {
             return this
                 .AddStep<TEdge>(new DerivedLabelNamesGremlinStep<TEdge>("inE"));
         }

-        public IGremlinQuery<TVertex> InV<TVertex>()
+        IGremlinQuery<TVertex> IGremlinQuery.InV<TVertex>()
         {
             return this
                 .Call<Vertex>("inV")
                 .OfType<TVertex>();
         }

-        public IGremlinQuery<TElement> Inject(params TElement[] elements)
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.Inject(params TElement[] elements)
         {
             return this
                 .Call("inject", elements);
         }

-        public IGremlinQuery<TElement> Limit(long limit)
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.Limit(long limit)
         {
             return this
                 .Call("limit", limit);
         }

-        public IGremlinQuery<TTarget> Local<TTarget>(Func<IGremlinQuery<TElement>, IGremlinQuery<TTarget>> localTraversal)
+        IGremlinQuery<TTarget> IGremlinQuery<TElement>.Local<TTarget>(Func<IGremlinQuery<TElement>, IGremlinQuery<TTarget>> localTraversal)
         {
             return this
                 .Call<TTarget>("local", localTraversal(this.ToAnonymous()));
         }

-        public IGremlinQuery<TTarget> Map<TTarget>(Func<IGremlinQuery<TElement>, IGremlinQuery<TTarget>> mapping)
+        IGremlinQuery<TTarget> IGremlinQuery<TElement>.Map<TTarget>(Func<IGremlinQuery<TElement>, IGremlinQuery<TTarget>> mapping)
         {
             return this
                 .Call<TTarget>("map", mapping(this.ToAnonymous()));
         }

-        public IGremlinQuery<TElement> Match(params Func<IGremlinQuery<TElement>, IGremlinQuery<TElement>>[] matchTraversals)
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.Match(params Func<IGremlinQuery<TElement>, IGremlinQuery<TElement>>[] matchTraversals)
         {
             return this
                 // ReSharper disable once CoVariantArrayConversion
                 .Call("match", matchTraversals.Select(traversal => traversal(this.ToAnonymous())).ToArray());
         }

-        public IGremlinQuery<TElement> Not(Func<IGremlinQuery<TElement>, IGremlinQuery> notTraversal)
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.Not(Func<IGremlinQuery<TElement>, IGremlinQuery> notTraversal)
         {
             return this
                 .Call("not", notTraversal(this.ToAnonymous()));
         }

-        public IGremlinQuery<TTarget> OfType<TTarget>()
+        IGremlinQuery<TTarget> IGremlinQuery.OfType<TTarget>()
         {
             return this
                 .AddStep<TTarget>(new DerivedLabelNamesGremlinStep<TTarget>("hasLabel"));
         }

-        public IGremlinQuery<TTarget> Optional<TTarget>(Func<IGremlinQuery<TElement>, IGremlinQuery<TTarget>> optionalTraversal)
+        IGremlinQuery<TTarget> IGremlinQuery<TElement>.Optional<TTarget>(Func<IGremlinQuery<TElement>, IGremlinQuery<TTarget>> optionalTraversal)
         {
             return this
                 .Call<TTarget>("optional", optionalTraversal(this.ToAnonymous()));
         }

-        public IGremlinQuery<TElement> Or(params Func<IGremlinQuery<TElement>, IGremlinQuery>[] orTraversals)
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.Or(params Func<IGremlinQuery<TElement>, IGremlinQuery>[] orTraversals)
         {
             return this.Call(
                 "or",
@@ -351,81 +339,81 @@
                             : list.Add(query2)));
         }

-        public IGremlinQuery<TElement> Order()
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.Order()
         {
             return this
                 .Call("order");
         }

-        public IGremlinQuery<Vertex> OtherV()
+        IGremlinQuery<Vertex> IGremlinQuery.OtherV()
         {
             return this
                 .Call<Vertex>("otherV");
         }

-        public IGremlinQuery<TEdge> OutE<TEdge>()
+        IGremlinQuery<TEdge> IGremlinQuery.OutE<TEdge>()
         {
             return this
                 .AddStep<TEdge>(new DerivedLabelNamesGremlinStep<TEdge>("outE"));
         }

-        public IGremlinQuery<TVertex> OutV<TVertex>()
+        IGremlinQuery<TVertex> IGremlinQuery.OutV<TVertex>()
         {
             return this
                 .Call<Vertex>("outV")
                 .OfType<TVertex>();
         }

-        public IGremlinQuery<Vertex> Out<TEdge>()
+        IGremlinQuery<Vertex> IGremlinQuery.Out<TEdge>()
         {
             return this
                 .AddStep<Vertex>(new DerivedLabelNamesGremlinStep<TEdge>("out"));
         }

-        public IGremlinQuery<string> Profile()
+        IGremlinQuery<string> IGremlinQuery<TElement>.Profile()
         {
             return this
                 .Call<string>("profile");
         }

-        public IGremlinQuery<TElement> Property<TProperty>(Expression<Func<TElement, TProperty>> propertyExpression, TProperty property)
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.Property<TProperty>(Expression<Func<TElement, TProperty>> propertyExpression, TProperty property)
         {
             if (propertyExpression.Body is MemberExpression memberExpression)
             {
                 if (memberExpression.Expression == propertyExpression.Parameters[0])
                 {
-                    return this.Property(memberExpression.Member.Name, property);
+                    return ((IGremlinQuery<TElement>)this).Property(memberExpression.Member.Name, property);
                 }
             }

             throw new NotSupportedException();
         }

-        public IGremlinQuery<TElement> Property(string key, object value)
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.Property(string key, object value)
         {
             return this
                 .Call("property", key, value);
         }

-        public IGremlinQuery<TElement> Range(long low, long high)
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.Range(long low, long high)
         {
             return this
                 .Call("range", low, high);
         }

-        public IGremlinQuery<TElement> Repeat(Func<IGremlinQuery<TElement>, IGremlinQuery<TElement>> repeatTraversal)
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.Repeat(Func<IGremlinQuery<TElement>, IGremlinQuery<TElement>> repeatTraversal)
         {
             return this
                 .Call("repeat", repeatTraversal(this.ToAnonymous()));
         }

-        public IGremlinQuery<TStep> Select<TStep>(StepLabel<TStep> label)
+        IGremlinQuery<TStep> IGremlinQuery.Select<TStep>(StepLabel<TStep> label)
         {
             return this
                 .Call<TStep>("select", label);
         }

-        public IGremlinQuery<(T1, T2)> Select<T1, T2>(StepLabel<T1> label1, StepLabel<T2> label2)
+        IGremlinQuery<(T1, T2)> IGremlinQuery.Select<T1, T2>(StepLabel<T1> label1, StepLabel<T2> label2)
         {
             return this
                 .Call<(T1, T2)>("select", label1, label2)
@@ -433,7 +421,7 @@
                 .AddStepLabelBinding(x => x.Item2, label2);
         }

-        public IGremlinQuery<(T1, T2, T3)> Select<T1, T2, T3>(StepLabel<T1> label1, StepLabel<T2> label2, StepLabel<T3> label3)
+        IGremlinQuery<(T1, T2, T3)> IGremlinQuery.Select<T1, T2, T3>(StepLabel<T1> label1, StepLabel<T2> label2, StepLabel<T3> label3)
         {
             return this
                 .Call<(T1, T2, T3)>("select", label1, label2, label3)
@@ -442,7 +430,7 @@
                 .AddStepLabelBinding(x => x.Item3, label3);
         }

-        public IGremlinQuery<(T1, T2, T3, T4)> Select<T1, T2, T3, T4>(StepLabel<T1> label1, StepLabel<T2> label2, StepLabel<T3> label3, StepLabel<T4> label4)
+        IGremlinQuery<(T1, T2, T3, T4)> IGremlinQuery.Select<T1, T2, T3, T4>(StepLabel<T1> label1, StepLabel<T2> label2, StepLabel<T3> label3, StepLabel<T4> label4)
         {
             return this
                 .Call<(T1, T2, T3, T4)>("select", label1, label2, label3, label4)
@@ -452,55 +440,55 @@
                 .AddStepLabelBinding(x => x.Item4, label4);
         }

-        public IGremlinQuery<TElement> SideEffect(Func<IGremlinQuery<TElement>, IGremlinQuery> sideEffectTraversal)
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.SideEffect(Func<IGremlinQuery<TElement>, IGremlinQuery> sideEffectTraversal)
         {
             return this
                 .Call("sideEffect", sideEffectTraversal(this.ToAnonymous()));
         }

-        public IGremlinQuery<TElement> Skip(long skip)
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.Skip(long skip)
         {
             return this
                 .Call("skip", skip);
         }

-        public IGremlinQuery<TElement> Sum(Scope scope)
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.Sum(Scope scope)
         {
             return this.Call("sum", scope);
         }

-        public IGremlinQuery<TElement> Times(int count)
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.Times(int count)
         {
             return this
                 .Call("times", count);
         }

-        public IGremlinQuery<TElement> Tail(long limit)
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.Tail(long limit)
         {
             return this
                 .Call("tail", limit);
         }

-        public IGremlinQuery<TElement> To<TStepLabel>(StepLabel<TStepLabel> stepLabel)
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.To<TStepLabel>(StepLabel<TStepLabel> stepLabel)
         {
             return this
                 .Call("to", stepLabel);
         }

-        public IGremlinQuery<TElement> To(Func<IGremlinQuery<TElement>, IGremlinQuery> toVertex)
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.To(Func<IGremlinQuery<TElement>, IGremlinQuery> toVertex)
         {
             return this
                 .Call("to", toVertex(this.ToAnonymous()));
         }

-        public IGremlinQuery<TElement> Unfold(IGremlinQuery<IEnumerable<TElement>> query)
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.Unfold(IGremlinQuery<IEnumerable<TElement>> query)
         {
             throw new NotImplementedException();    //Bug!
                                                     //return query
                                                     //    .Call<TElement>("unfold");
         }

-        public IGremlinQuery<TTarget> Union<TTarget>(params Func<IGremlinQuery<TElement>, IGremlinQuery<TTarget>>[] unionTraversals)
+        IGremlinQuery<TTarget> IGremlinQuery<TElement>.Union<TTarget>(params Func<IGremlinQuery<TElement>, IGremlinQuery<TTarget>>[] unionTraversals)
         {
             return this
                 .Call<TTarget>("union", unionTraversals
@@ -508,30 +496,30 @@
                     .ToImmutableList<object>());
         }

-        public IGremlinQuery<TElement> Until(Func<IGremlinQuery<TElement>, IGremlinQuery> untilTraversal)
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.Until(Func<IGremlinQuery<TElement>, IGremlinQuery> untilTraversal)
         {
             return this
                 .Call("until", untilTraversal(this.ToAnonymous()));
         }

-        public IGremlinQuery<Vertex> V(params object[] ids)
+        IGremlinQuery<Vertex> IGremlinQuery.V(params object[] ids)
         {
             return this
                 .Call<Vertex>("V", ids);
         }

-        public IGremlinQuery<TTarget> Values<TTarget>(params Expression<Func<TElement, TTarget>>[] projections)
+        IGremlinQuery<TTarget> IGremlinQuery<TElement>.Values<TTarget>(params Expression<Func<TElement, TTarget>>[] projections)
         {
             return this.AddStep<TTarget>(new ValuesGremlinStep<TElement, TTarget>(projections));
         }

-        public IGremlinQuery<TElement> Where(Func<IGremlinQuery<TElement>, IGremlinQuery> filterTraversal)
+        IGremlinQuery<TElement> IGremlinQuery<TElement>.Where(Func<IGremlinQuery<TElement>, IGremlinQuery> filterTraversal)
         {
             return this
                 .Call("where", filterTraversal(this.ToAnonymous()));
         }

-        public GroovyExpressionState Serialize(StringBuilder stringBuilder, GroovyExpressionState state)
+        GroovyExpressionState IGroovySerializable.Serialize(StringBuilder stringBuilder, GroovyExpressionState state)
         {
             foreach (var step in this.Steps)
             {


Fullscreen crash if no game actions are present

--- source/Playnite.FullscreenApp/ViewModels/GameDetailsViewModel.cs
+++ source/Playnite.FullscreenApp/ViewModels/GameDetailsViewModel.cs
@@ -207,7 +207,7 @@
                 items.Add(new GameActionItem(InstallGameCommand, resources.GetString("LOCInstallGame")));
             }

-            Game.GameActions.Where(a => !a.IsPlayAction).ForEach(a => items.Add(new GameActionItem(ActivateActionCommand, a, a.Name)));
+            Game.GameActions?.Where(a => !a.IsPlayAction).ForEach(a => items.Add(new GameActionItem(ActivateActionCommand, a, a.Name)));

             items.Add(new GameActionItem(ToggleFavoritesCommand, Game.Favorite ? resources.GetString("LOCRemoveFavoriteGame") : resources.GetString("LOCFavoriteGame")));
             items.Add(new GameActionItem(ToggleVisibilityCommand, Game.Hidden ? resources.GetString("LOCUnHideGame") : resources.GetString("LOCHideGame")));


Updated EventLogSummaryTable

Updated EventLogSummaryTable

--- src/Ampla.LogReader/EventLogs/Statistics/EventLogSummaryTable.cs
+++ src/Ampla.LogReader/EventLogs/Statistics/EventLogSummaryTable.cs
@@ -1,4 +1,4 @@
-using System.Collections.Generic;
+using System;
 using System.Data;
 using Ampla.LogReader.Statistics;

@@ -7,15 +7,26 @@
     public class EventLogSummaryTable : IStatisticTable<EventLogReader>
     {
         private readonly DataTable dataTable;
+        private readonly DateTime last1Hr;
+        private readonly DateTime last24Hrs;

         public EventLogSummaryTable(string name)
         {
+            DateTime nowUtc = DateTime.UtcNow;
+            last1Hr = nowUtc.AddHours(-1);
+            last24Hrs = nowUtc.AddDays(-1);
             Name = name;
             dataTable = new DataTable(Name);
             dataTable.Columns.Add("EventLog", typeof (string));
-            dataTable.Columns.Add("Errors", typeof(int));
-            dataTable.Columns.Add("Warnings", typeof(int));
-            dataTable.Columns.Add("Infos", typeof(int));
+            dataTable.Columns.Add("Error-1hr", typeof(int));
+            dataTable.Columns.Add("Warning-1hr", typeof(int));
+            dataTable.Columns.Add("Information-1hr", typeof(int));
+            dataTable.Columns.Add("Error-24hrs", typeof(int));
+            dataTable.Columns.Add("Warning-24hrs", typeof(int));
+            dataTable.Columns.Add("Information-24hrs", typeof(int));
+            dataTable.Columns.Add("Error", typeof(int));
+            dataTable.Columns.Add("Warning", typeof(int));
+            dataTable.Columns.Add("Information", typeof(int));
             dataTable.Columns.Add("Total", typeof(int));
         }

@@ -23,11 +34,24 @@
         {
             entry.Read();
             EventLogEntryTypeStatistic statistic = new EventLogEntryTypeStatistic(entry.Name);
+            EventLogEntryTypeStatistic lastHour = new EventLogEntryTypeStatistic(entry.Name);
+            EventLogEntryTypeStatistic lastDay = new EventLogEntryTypeStatistic(entry.Name);
             foreach (SimpleEventLogEntry logEntry in entry.Entries)
             {
+                if (logEntry.CallTime >= last24Hrs)
+                {
+                    lastDay.Add(logEntry);
+                    if (logEntry.CallTime >= last1Hr)
+                    {
+                        lastHour.Add(logEntry);
+                    }
+                }
                 statistic.Add(logEntry);
             }
-            dataTable.Rows.Add(entry.Name, statistic.ErrorCount, statistic.WarningCount, statistic.InformationCount, statistic.TotalCount);
+            dataTable.Rows.Add(entry.Name,
+                lastHour.ErrorCount, lastHour.WarningCount, lastHour.InformationCount,
+                lastDay.ErrorCount, lastDay.WarningCount, lastDay.InformationCount,
+                statistic.ErrorCount, statistic.WarningCount, statistic.InformationCount, statistic.TotalCount);
         }

         public DataTable GetData()


Unsubscribe from stuff in DevTools MainViewModel.

--- src/Avalonia.Diagnostics/Diagnostics/ViewModels/MainViewModel.cs
+++ src/Avalonia.Diagnostics/Diagnostics/ViewModels/MainViewModel.cs
@@ -1,4 +1,5 @@
 using System;
+using System.ComponentModel;
 using Avalonia.Controls;
 using Avalonia.Diagnostics.Models;
 using Avalonia.Input;
@@ -12,6 +13,7 @@
         private readonly TreePageViewModel _logicalTree;
         private readonly TreePageViewModel _visualTree;
         private readonly EventsPageViewModel _events;
+        private readonly IDisposable _pointerOverSubscription;
         private ViewModelBase _content;
         private int _selectedTab;
         private string _focusedControl;
@@ -25,16 +27,9 @@
             _events = new EventsPageViewModel(root);

             UpdateFocusedControl();
-            KeyboardDevice.Instance.PropertyChanged += (s, e) =>
-            {
-                if (e.PropertyName == nameof(KeyboardDevice.Instance.FocusedElement))
-                {
-                    UpdateFocusedControl();
-                }
-            };
-
+            KeyboardDevice.Instance.PropertyChanged += KeyboardPropertyChanged;
             SelectedTab = 0;
-            root.GetObservable(TopLevel.PointerOverElementProperty)
+            _pointerOverSubscription = root.GetObservable(TopLevel.PointerOverElementProperty)
                 .Subscribe(x => PointerOverElement = x?.GetType().Name);
             Console = new ConsoleViewModel(UpdateConsoleContext);
         }
@@ -129,6 +124,8 @@

         public void Dispose()
         {
+            KeyboardDevice.Instance.PropertyChanged -= KeyboardPropertyChanged;
+            _pointerOverSubscription.Dispose();
             _logicalTree.Dispose();
             _visualTree.Dispose();
         }
@@ -137,5 +134,13 @@
         {
             FocusedControl = KeyboardDevice.Instance.FocusedElement?.GetType().Name;
         }
+
+        private void KeyboardPropertyChanged(object sender, PropertyChangedEventArgs e)
+        {
+            if (e.PropertyName == nameof(KeyboardDevice.Instance.FocusedElement))
+            {
+                UpdateFocusedControl();
+            }
+        }
     }
 }