Browse Source

Added an option to disable analytics

Krzysztof Krysiński 4 months ago
parent
commit
a5da800ea1

+ 3 - 0
src/PixiEditor.Extensions.CommonApi/UserPreferences/PreferencesConstants.cs

@@ -30,4 +30,7 @@ public static class PreferencesConstants
 
     public const string OpenDirectoryOnExport = "OpenDirectoryOnExport";
     public const bool OpenDirectoryOnExportDefault = true;
+
+    public const string AnalyticsEnabled = "AnalyticsEnabled";
+    public const bool AnalyticsEnabledDefault = true;
 }

+ 5 - 0
src/PixiEditor.Extensions.CommonApi/UserPreferences/Settings/PixiEditor/PixiEditorSettings.cs

@@ -64,4 +64,9 @@ public static class PixiEditorSettings
 
         public static SyncedSetting<bool> ShowLayerCount { get; } = SyncedSetting.NonOwned(PixiEditor, true);
     }
+
+    public static class Analytics
+    {
+        public static SyncedSetting<bool> AnalyticsEnabled { get; } = SyncedSetting.NonOwned(PixiEditor, true);
+    }
 }

+ 3 - 1
src/PixiEditor/Data/Localization/Languages/en.json

@@ -987,5 +987,7 @@
   "ERR_UNKNOWN_IMG_FORMAT": "Unknown image format '{0}'.",
   "ERR_FAILED_GENERATE_SPRITE_SHEET": "Failed generating sprite sheet",
   "ERR_NO_RENDERER": "Animation renderer not found.",
-  "ERR_RENDERING_FAILED": "Rendering failed"
+  "ERR_RENDERING_FAILED": "Rendering failed",
+  "ENABLE_ANALYTICS": "Send anonymous analytics",
+  "ANALYTICS_INFO": "We collect anonymous usage data to improve PixiEditor. No personal data is collected."
 }

+ 31 - 11
src/PixiEditor/Models/AnalyticsAPI/AnalyticsPeriodicReporter.cs

@@ -1,4 +1,7 @@
-using PixiEditor.Helpers;
+using PixiEditor.Extensions.CommonApi.UserPreferences;
+using PixiEditor.Extensions.CommonApi.UserPreferences.Settings;
+using PixiEditor.Extensions.CommonApi.UserPreferences.Settings.PixiEditor;
+using PixiEditor.Helpers;
 
 namespace PixiEditor.Models.AnalyticsAPI;
 
@@ -6,11 +9,11 @@ public class AnalyticsPeriodicReporter
 {
     private int _sendExceptions = 0;
     private bool _resumeSession;
-    
+
     private readonly SemaphoreSlim _semaphore = new(1, 1);
     private readonly AnalyticsClient _client;
     private readonly PeriodicPerformanceReporter _performanceReporter;
-    
+
     private readonly List<AnalyticEvent> _backlog = new();
     private readonly CancellationTokenSource _cancellationToken = new();
 
@@ -19,25 +22,30 @@ public class AnalyticsPeriodicReporter
     public static AnalyticsPeriodicReporter? Instance { get; private set; }
 
     public Guid SessionId { get; private set; }
-    
+
     public AnalyticsPeriodicReporter(AnalyticsClient client)
     {
         if (Instance != null)
             throw new InvalidOperationException("There's already a AnalyticsReporter present");
 
         Instance = this;
-        
+
         _client = client;
         _performanceReporter = new PeriodicPerformanceReporter(this);
+
+        PixiEditorSettings.Analytics.AnalyticsEnabled.ValueChanged += EnableAnalyticsOnValueChanged;
     }
 
     public void Start(Guid? sessionId)
     {
+        if (!PixiEditorSettings.Analytics.AnalyticsEnabled.Value)
+            return;
+
         if (sessionId != null)
         {
             SessionId = sessionId.Value;
             _resumeSession = true;
-            
+
             _backlog.Add(new AnalyticEvent { Time = DateTime.UtcNow, EventType = AnalyticEventTypes.ResumeSession });
         }
 
@@ -47,7 +55,7 @@ public class AnalyticsPeriodicReporter
 
     public async Task StopAsync()
     {
-        _cancellationToken.Cancel();
+        await _cancellationToken.CancelAsync();
 
         await _client.EndSessionAsync(SessionId).WaitAsync(TimeSpan.FromSeconds(1));
     }
@@ -59,7 +67,7 @@ public class AnalyticsPeriodicReporter
         {
             return;
         }
-        
+
         Task.Run(() =>
         {
             _semaphore.Wait();
@@ -97,7 +105,7 @@ public class AnalyticsPeriodicReporter
             {
                 if (_backlog.Any(x => x.ExpectingEndTimeReport))
                     WaitForEndTimes();
-                
+
                 await SendBacklogAsync();
 
                 await Task.Delay(TimeSpan.FromSeconds(10));
@@ -137,7 +145,7 @@ public class AnalyticsPeriodicReporter
             {
                 return;
             }
-            
+
             var result = await _client.SendEventsAsync(SessionId, _backlog, _cancellationToken.Token);
             _backlog.Clear();
 
@@ -184,7 +192,7 @@ public class AnalyticsPeriodicReporter
 
         if (!result)
         {
-            _cancellationToken.Cancel();
+            await _cancellationToken.CancelAsync();
         }
     }
 
@@ -196,4 +204,16 @@ public class AnalyticsPeriodicReporter
             _sendExceptions++;
         }
     }
+
+    private void EnableAnalyticsOnValueChanged(Setting<bool> setting, bool enabled)
+    {
+        if (enabled)
+        {
+            Start(null);
+        }
+        else
+        {
+            StopAsync();
+        }
+    }
 }

+ 7 - 0
src/PixiEditor/ViewModels/UserPreferences/Settings/GeneralSettings.cs

@@ -46,4 +46,11 @@ internal class GeneralSettings : SettingsGroup
             }
         }
     }
+
+    private bool isAnalyticsEnabled = GetPreference(PreferencesConstants.AnalyticsEnabled, PreferencesConstants.AnalyticsEnabledDefault);
+    public bool AnalyticsEnabled
+    {
+        get => isAnalyticsEnabled;
+        set => RaiseAndUpdatePreference(ref isAnalyticsEnabled, value);
+    }
 }

+ 12 - 0
src/PixiEditor/Views/Windows/Settings/SettingsWindow.axaml

@@ -57,6 +57,11 @@
                         <Style Selector=":is(Control).leftOffset">
                             <Setter Property="Margin" Value="20, 0, 0, 0" />
                         </Style>
+                        <Style Selector=":is(TextBlock).subtext">
+                            <Setter Property="FontSize" Value="12" />
+                            <Setter Property="Foreground" Value="{DynamicResource ThemeForegroundLowBrush}" />
+                            <Setter Property="TextWrapping" Value="Wrap" />
+                        </Style>
                     </Grid.Styles>
                     <ScrollViewer>
                         <ScrollViewer.IsVisible>
@@ -208,6 +213,13 @@
                             <CheckBox Classes="leftOffset"
                                       IsChecked="{Binding SettingsSubViewModel.General.IsDebugModeEnabled}"
                                       ui:Translator.Key="ENABLE_DEBUG_MODE" d:Content="Enable Debug Mode" />
+
+                            <TextBlock ui:Translator.Key="MISC"/>
+
+                            <CheckBox Classes="leftOffset"
+                                      IsChecked="{Binding SettingsSubViewModel.General.AnalyticsEnabled, Mode=TwoWay}"
+                                      ui:Translator.Key="ENABLE_ANALYTICS" d:Content="Enable Analytics" />
+                            <TextBlock ui:Translator.Key="ANALYTICS_INFO" Classes="leftOffset subtext"/>
                             <!--<Label Classes="{StaticResource SettingsText}" VerticalAlignment="Center">
                             <ui1:Hyperlink Command="{cmds:Command PixiEditor.Debug.OpenCrashReportsDirectory}" Style="{StaticResource SettingsLink}">
                                 <Run ui:Translator.Key="OPEN_CRASH_REPORTS_DIR" d:Text="Open crash reports directory"/>