CPKreuz 11 tháng trước cách đây
mục cha
commit
ade47eb5df

+ 14 - 5
src/PixiEditor.Builder/build/Program.cs

@@ -25,6 +25,8 @@ public class BuildContext : FrostingContext
 
     public string CrashReportWebhookUrl { get; set; }
 
+    public string AnalyticsUrl { get; set; }
+
     public string BackedUpConstants { get; set; }
 
     public string BuildConfiguration { get; set; } = "Release";
@@ -38,10 +40,8 @@ public class BuildContext : FrostingContext
     public BuildContext(ICakeContext context)
         : base(context)
     {
-        bool hasWebhook = context.Arguments.HasArgument("crash-report-webhook-url");
-        CrashReportWebhookUrl = hasWebhook
-            ? context.Arguments.GetArgument("crash-report-webhook-url")
-            : string.Empty;
+        CrashReportWebhookUrl = GetArgumentOrDefault(context, "crash-report-webhook-url", string.Empty);
+        AnalyticsUrl = GetArgumentOrDefault(context, "analytics-url", string.Empty);
 
         bool hasCustomProjectPath = context.Arguments.HasArgument("project-path");
         if (hasCustomProjectPath)
@@ -69,6 +69,14 @@ public class BuildContext : FrostingContext
 
         Runtime = context.Arguments.GetArgument("runtime");
     }
+
+    private static string GetArgumentOrDefault(ICakeContext context, string argumentName, string defaultValue)
+    {
+        var arguments = context.Arguments;
+
+        var hasArgument = arguments.HasArgument(argumentName);
+        return hasArgument ? arguments.GetArgument(argumentName) : defaultValue;
+    }
 }
 
 [TaskName("Default")]
@@ -101,7 +109,8 @@ public sealed class ReplaceSpecialStringsTask : FrostingTask<BuildContext>
     private string ReplaceSpecialStrings(BuildContext context, string fileContent)
     {
         string result = fileContent
-            .Replace("${crash-report-webhook-url}", context.CrashReportWebhookUrl);
+            .Replace("${crash-report-webhook-url}", context.CrashReportWebhookUrl)
+            .Replace("${analytics-url}", context.AnalyticsUrl);
 
         return result;
     }

+ 2 - 0
src/PixiEditor/BuildConstants.cs

@@ -3,4 +3,6 @@ namespace PixiEditor;
 public static class BuildConstants
 {
     public const string CrashReportWebhookUrl = "${crash-report-webhook-url}";
+
+    public const string AnalyticsUrl = "${analytics-url}";
 }

+ 30 - 5
src/PixiEditor/Helpers/ServiceCollectionHelpers.cs

@@ -1,4 +1,5 @@
-using System.Linq;
+using System.Diagnostics;
+using System.Linq;
 using System.Reflection;
 using Microsoft.Extensions.DependencyInjection;
 using PixiEditor.AnimationRenderer.Core;
@@ -75,9 +76,6 @@ internal static class ServiceCollectionHelpers
             .AddSingleton<LayoutManager>()
             .AddSingleton<LayoutViewModel>()
             .AddSingleton(x => new ExtensionsViewModel(x.GetService<ViewModels_ViewModelMain>(), extensionLoader))
-            // Analytics
-            .AddSingleton<AnalyticsClient>(_ => new AnalyticsClient(Environment.GetEnvironmentVariable("PixiEditorAnalytics")))
-            .AddSingleton<AnalyticsPeriodicReporter>()
             // Controllers
             .AddSingleton<ShortcutController>()
             .AddSingleton<CommandController>()
@@ -138,7 +136,34 @@ internal static class ServiceCollectionHelpers
             .AddSingleton<PaletteFileParser, PixiPaletteParser>()
             // Palette data sources
             .AddSingleton<PaletteListDataSource, LocalPalettesFetcher>()
-            .AddMenuBuilders();
+            .AddMenuBuilders()
+            .AddAnalyticsAsNeeded();
+    }
+
+    private static IServiceCollection AddAnalyticsAsNeeded(this IServiceCollection collection)
+    {
+        string url = BuildConstants.AnalyticsUrl;
+
+        if (url == "${analytics-url}")
+        {
+            url = null;
+            SetDebugUrl(ref url);
+        }
+
+        if (!string.IsNullOrWhiteSpace(url))
+        {
+            collection
+                .AddSingleton<AnalyticsClient>(_ => new AnalyticsClient(url))
+                .AddSingleton<AnalyticsPeriodicReporter>();
+        }
+
+        return collection;
+
+        [Conditional("DEBUG")]
+        static void SetDebugUrl(ref string? url)
+        {
+            url = Environment.GetEnvironmentVariable("PixiEditorAnalytics");
+        }
     }
 
     private static IServiceCollection AddMenuBuilders(this IServiceCollection collection)

+ 19 - 14
src/PixiEditor/Models/AnalyticsAPI/Analytics.cs

@@ -9,19 +9,19 @@ namespace PixiEditor.Models.AnalyticsAPI;
 
 public static class Analytics
 {
-    public static AnalyticEvent SendStartup(StartupPerformance startup) =>
+    public static AnalyticEvent? SendStartup(StartupPerformance startup) =>
         SendEvent(AnalyticEventTypes.Startup, startup.GetData());
 
-    public static AnalyticEvent SendCreateDocument(int width, int height) =>
+    public static AnalyticEvent? SendCreateDocument(int width, int height) =>
         SendEvent(AnalyticEventTypes.CreateDocument, ("Width", width), ("Height", height));
 
-    internal static AnalyticEvent SendOpenFile(IoFileType fileType, long fileSize, VecI size) =>
+    internal static AnalyticEvent? SendOpenFile(IoFileType fileType, long fileSize, VecI size) =>
         SendEvent(AnalyticEventTypes.OpenFile, ("FileType", fileType.PrimaryExtension), ("FileSize", fileSize), ("Width", size.X), ("Height", size.Y));
 
-    internal static AnalyticEvent SendCreateNode(Type nodeType) =>
+    internal static AnalyticEvent? SendCreateNode(Type nodeType) =>
         SendEvent(AnalyticEventTypes.CreateNode, ("NodeType", nodeType.GetCustomAttribute<NodeInfoAttribute>()?.UniqueName));
 
-    internal static AnalyticEvent SendCreateKeyframe(int position, string type, int fps, int duration, int totalKeyframes) =>
+    internal static AnalyticEvent? SendCreateKeyframe(int position, string type, int fps, int duration, int totalKeyframes) =>
         SendEvent(
             AnalyticEventTypes.CreateKeyframe,
             ("Position", position),
@@ -30,24 +30,31 @@ public static class Analytics
             ("Duration", duration),
             ("TotalKeyframes", totalKeyframes));
 
-    internal static AnalyticEvent SendCloseDocument() => SendEvent(AnalyticEventTypes.CloseDocument);
+    internal static AnalyticEvent? SendCloseDocument() => SendEvent(AnalyticEventTypes.CloseDocument);
     
-    internal static AnalyticEvent SendOpenExample(string fileName) => SendEvent(AnalyticEventTypes.OpenExample, ("FileName", fileName));
+    internal static AnalyticEvent? SendOpenExample(string fileName) => SendEvent(AnalyticEventTypes.OpenExample, ("FileName", fileName));
 
-    internal static AnalyticEvent SendUseTool(IToolHandler? tool, VecD positionOnCanvas, VecD documentSize) =>
+    internal static AnalyticEvent? SendUseTool(IToolHandler? tool, VecD positionOnCanvas, VecD documentSize) =>
         SendEvent(AnalyticEventTypes.UseTool, ("Tool", tool?.ToolName), ("Position", new VecD(documentSize.X / positionOnCanvas.X, documentSize.Y / positionOnCanvas.Y)));
 
-    internal static AnalyticEvent SendSwitchToTool(IToolHandler? newTool, IToolHandler? oldTool, ICommandExecutionSourceInfo? sourceInfo) =>
+    internal static AnalyticEvent? SendSwitchToTool(IToolHandler? newTool, IToolHandler? oldTool, ICommandExecutionSourceInfo? sourceInfo) =>
         SendEvent(AnalyticEventTypes.SwitchTool, ("NewTool", newTool?.ToolName), ("OldTool", oldTool?.ToolName), ("Source", sourceInfo));
 
-    internal static AnalyticEvent SendCommand(string commandName, ICommandExecutionSourceInfo? source) =>
+    internal static AnalyticEvent? SendCommand(string commandName, ICommandExecutionSourceInfo? source) =>
         SendEvent(AnalyticEventTypes.GeneralCommand, ("CommandName", commandName), ("Source", source));
     
-    private static AnalyticEvent SendEvent(string name, params (string, object)[] data) =>
+    private static AnalyticEvent? SendEvent(string name, params (string, object)[] data) =>
         SendEvent(name, data.ToDictionary());
 
-    private static AnalyticEvent SendEvent(string name, Dictionary<string, object> data)
+    private static AnalyticEvent? SendEvent(string name, Dictionary<string, object> data)
     {
+        var reporter = AnalyticsPeriodicReporter.Instance;
+
+        if (reporter == null)
+        {
+            return null;
+        }
+
         var e = new AnalyticEvent
         {
             EventType = name,
@@ -55,8 +62,6 @@ public static class Analytics
             Data = data
         };
         
-        var reporter = AnalyticsPeriodicReporter.Instance;
-
         reporter.AddEvent(e);
 
         return e;

+ 1 - 1
src/PixiEditor/Models/AnalyticsAPI/AnalyticsPeriodicReporter.cs

@@ -14,7 +14,7 @@ public class AnalyticsPeriodicReporter
 
     private DateTime lastActivity;
 
-    public static AnalyticsPeriodicReporter Instance { get; private set; }
+    public static AnalyticsPeriodicReporter? Instance { get; private set; }
 
     public Guid SessionId { get; private set; }