From 7ba03ed24f102dc7873a5e603f6d12990a46d232 Mon Sep 17 00:00:00 2001 From: Mykhailo Pylyp Date: Thu, 25 Mar 2021 13:11:36 +0200 Subject: [PATCH] Add telemetry to ColorPicker (#10413) --- .../ColorPickerUI/ColorEditorWindow.xaml.cs | 20 +--- .../Controls/ColorFormatControl.xaml.cs | 1 + .../Controls/ColorPickerControl.xaml.cs | 4 +- .../ColorPickerUI/Helpers/AppStateHandler.cs | 112 ++++++++++++++---- .../Helpers/NativeEventWaiter.cs | 2 +- .../Helpers/SessionEventHelper.cs | 39 ++++++ .../ColorPickerUI/Helpers/ZoomWindowHelper.cs | 2 +- .../ColorPickerUI/Keyboard/KeyboardMonitor.cs | 20 +--- .../Telemetry/ColorPickerCancelledEvent.cs | 16 --- .../Telemetry/ColorPickerSession.cs | 39 ++++++ .../Telemetry/ColorPickerShowEvent.cs | 16 --- .../Telemetry/ColorPickerZoomOpenedEvent.cs | 16 --- .../ViewModels/ColorEditorViewModel.cs | 1 + .../ColorPickerUI/ViewModels/MainViewModel.cs | 9 +- .../ColorPickerUI/Views/ColorEditorView.xaml | 11 +- .../Views/ColorEditorView.xaml.cs | 21 ++-- 16 files changed, 197 insertions(+), 132 deletions(-) create mode 100644 src/modules/colorPicker/ColorPickerUI/Helpers/SessionEventHelper.cs delete mode 100644 src/modules/colorPicker/ColorPickerUI/Telemetry/ColorPickerCancelledEvent.cs create mode 100644 src/modules/colorPicker/ColorPickerUI/Telemetry/ColorPickerSession.cs delete mode 100644 src/modules/colorPicker/ColorPickerUI/Telemetry/ColorPickerShowEvent.cs delete mode 100644 src/modules/colorPicker/ColorPickerUI/Telemetry/ColorPickerZoomOpenedEvent.cs diff --git a/src/modules/colorPicker/ColorPickerUI/ColorEditorWindow.xaml.cs b/src/modules/colorPicker/ColorPickerUI/ColorEditorWindow.xaml.cs index ccb3910af1..e58ff6017b 100644 --- a/src/modules/colorPicker/ColorPickerUI/ColorEditorWindow.xaml.cs +++ b/src/modules/colorPicker/ColorPickerUI/ColorEditorWindow.xaml.cs @@ -2,19 +2,8 @@ // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Shapes; +using ColorPicker.Helpers; namespace ColorPicker { @@ -23,16 +12,19 @@ namespace ColorPicker /// public partial class ColorEditorWindow : Window { - public ColorEditorWindow() + private readonly AppStateHandler _appStateHandler; + + public ColorEditorWindow(AppStateHandler appStateHandler) { InitializeComponent(); + _appStateHandler = appStateHandler; Closing += ColorEditorWindow_Closing; } private void ColorEditorWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e) { e.Cancel = true; - this.Hide(); + _appStateHandler.EndUserSession(); } } } diff --git a/src/modules/colorPicker/ColorPickerUI/Controls/ColorFormatControl.xaml.cs b/src/modules/colorPicker/ColorPickerUI/Controls/ColorFormatControl.xaml.cs index 8d475b9fe4..5a64b54c77 100644 --- a/src/modules/colorPicker/ColorPickerUI/Controls/ColorFormatControl.xaml.cs +++ b/src/modules/colorPicker/ColorPickerUI/Controls/ColorFormatControl.xaml.cs @@ -56,6 +56,7 @@ namespace ColorPicker.Controls private void CopyToClipboardButton_Click(object sender, RoutedEventArgs e) { ClipboardHelper.CopyToClipboard(ColorTextRepresentationTextBlock.Text); + SessionEventHelper.Event.EditorColorCopiedToClipboard = true; if (!_copyIndicatorVisible) { AppearCopiedIndicator(); diff --git a/src/modules/colorPicker/ColorPickerUI/Controls/ColorPickerControl.xaml.cs b/src/modules/colorPicker/ColorPickerUI/Controls/ColorPickerControl.xaml.cs index a8148db5ad..7af9ae29f0 100644 --- a/src/modules/colorPicker/ColorPickerUI/Controls/ColorPickerControl.xaml.cs +++ b/src/modules/colorPicker/ColorPickerUI/Controls/ColorPickerControl.xaml.cs @@ -205,6 +205,7 @@ namespace ColorPicker.Controls detailsStackPanel.BeginAnimation(StackPanel.OpacityProperty, opacityAppear); detailsGrid.BeginAnimation(Grid.HeightProperty, resize); CurrentColorButton.IsEnabled = false; + SessionEventHelper.Event.EditorAdjustColorOpened = true; } } @@ -239,8 +240,8 @@ namespace ColorPicker.Controls private void OKButton_Click(object sender, RoutedEventArgs e) { HideDetails(); - SelectedColorChangedCommand.Execute(_currentColor); + SessionEventHelper.Event.EditorColorAdjusted = true; } private void CancelButton_Click(object sender, RoutedEventArgs e) @@ -258,6 +259,7 @@ namespace ColorPicker.Controls { var selectedColor = ((SolidColorBrush)((Button)sender).Background).Color; SelectedColorChangedCommand.Execute(selectedColor); + SessionEventHelper.Event.EditorSimilarColorPicked = true; } private void ValueGradientGrid_MouseMove(object sender, MouseEventArgs e) diff --git a/src/modules/colorPicker/ColorPickerUI/Helpers/AppStateHandler.cs b/src/modules/colorPicker/ColorPickerUI/Helpers/AppStateHandler.cs index cae2ef4fa0..2b303cb663 100644 --- a/src/modules/colorPicker/ColorPickerUI/Helpers/AppStateHandler.cs +++ b/src/modules/colorPicker/ColorPickerUI/Helpers/AppStateHandler.cs @@ -5,7 +5,9 @@ using System; using System.ComponentModel.Composition; using System.Windows; +using ColorPicker.Settings; using ColorPicker.ViewModelContracts; +using Microsoft.PowerToys.Settings.UI.Library.Enumerations; namespace ColorPicker.Helpers { @@ -13,15 +15,17 @@ namespace ColorPicker.Helpers public class AppStateHandler { private readonly IColorEditorViewModel _colorEditorViewModel; + private readonly IUserSettings _userSettings; private ColorEditorWindow _colorEditorWindow; private bool _colorPickerShown; private object _colorPickerVisibilityLock = new object(); [ImportingConstructor] - public AppStateHandler(IColorEditorViewModel colorEditorViewModel) + public AppStateHandler(IColorEditorViewModel colorEditorViewModel, IUserSettings userSettings) { Application.Current.MainWindow.Closed += MainWindow_Closed; _colorEditorViewModel = colorEditorViewModel; + _userSettings = userSettings; } public event EventHandler AppShown; @@ -30,48 +34,110 @@ namespace ColorPicker.Helpers public event EventHandler AppClosed; - public void ShowColorPicker() + public void StartUserSession() { lock (_colorPickerVisibilityLock) { - if (!_colorPickerShown) + if (!_colorPickerShown && !IsColorPickerEditorVisible()) { - AppShown?.Invoke(this, EventArgs.Empty); - Application.Current.MainWindow.Opacity = 0; - Application.Current.MainWindow.Visibility = Visibility.Visible; - _colorPickerShown = true; + SessionEventHelper.Start(_userSettings.ActivationAction.Value); + } + + if (_userSettings.ActivationAction.Value == ColorPickerActivationAction.OpenEditor) + { + ShowColorPickerEditor(); + } + else + { + ShowColorPicker(); } } } - public void HideColorPicker() + public void EndUserSession() { lock (_colorPickerVisibilityLock) { - if (_colorPickerShown) + if (IsColorPickerEditorVisible() || _colorPickerShown) { - Application.Current.MainWindow.Opacity = 0; - Application.Current.MainWindow.Visibility = Visibility.Collapsed; - AppHidden?.Invoke(this, EventArgs.Empty); - _colorPickerShown = false; + if (IsColorPickerEditorVisible()) + { + HideColorPickerEditor(); + } + else + { + HideColorPicker(); + } + + SessionEventHelper.End(); } } } - public void ShowColorPickerEditor() + public void OnColorPickerMouseDown() + { + if (_userSettings.ActivationAction.Value == ColorPickerActivationAction.OpenColorPickerAndThenEditor || _userSettings.ActivationAction.Value == ColorPickerActivationAction.OpenEditor) + { + lock (_colorPickerVisibilityLock) + { + HideColorPicker(); + } + + ShowColorPickerEditor(); + } + else + { + EndUserSession(); + } + } + + public static void SetTopMost() + { + Application.Current.MainWindow.Topmost = false; + Application.Current.MainWindow.Topmost = true; + } + + private void ShowColorPicker() + { + if (!_colorPickerShown) + { + AppShown?.Invoke(this, EventArgs.Empty); + Application.Current.MainWindow.Opacity = 0; + Application.Current.MainWindow.Visibility = Visibility.Visible; + _colorPickerShown = true; + } + } + + private void HideColorPicker() + { + if (_colorPickerShown) + { + Application.Current.MainWindow.Opacity = 0; + Application.Current.MainWindow.Visibility = Visibility.Collapsed; + AppHidden?.Invoke(this, EventArgs.Empty); + _colorPickerShown = false; + } + } + + private void ShowColorPickerEditor() { if (_colorEditorWindow == null) { - _colorEditorWindow = new ColorEditorWindow(); + _colorEditorWindow = new ColorEditorWindow(this); _colorEditorWindow.Content = _colorEditorViewModel; _colorEditorViewModel.OpenColorPickerRequested += ColorEditorViewModel_OpenColorPickerRequested; + _colorEditorViewModel.OpenColorPickerRequested += (object sender, EventArgs e) => + { + SessionEventHelper.Event.EditorColorPickerOpened = true; + }; } _colorEditorViewModel.Initialize(); _colorEditorWindow.Show(); + SessionEventHelper.Event.EditorOpened = true; } - public void HideColorPickerEditor() + private void HideColorPickerEditor() { if (_colorEditorWindow != null) { @@ -79,7 +145,7 @@ namespace ColorPicker.Helpers } } - public bool IsColorPickerEditorVisible() + private bool IsColorPickerEditorVisible() { if (_colorEditorWindow != null) { @@ -90,12 +156,6 @@ namespace ColorPicker.Helpers return false; } - public static void SetTopMost() - { - Application.Current.MainWindow.Topmost = false; - Application.Current.MainWindow.Topmost = true; - } - private void MainWindow_Closed(object sender, EventArgs e) { AppClosed?.Invoke(this, EventArgs.Empty); @@ -103,7 +163,11 @@ namespace ColorPicker.Helpers private void ColorEditorViewModel_OpenColorPickerRequested(object sender, EventArgs e) { - ShowColorPicker(); + lock (_colorPickerVisibilityLock) + { + ShowColorPicker(); + } + _colorEditorWindow.Hide(); } } diff --git a/src/modules/colorPicker/ColorPickerUI/Helpers/NativeEventWaiter.cs b/src/modules/colorPicker/ColorPickerUI/Helpers/NativeEventWaiter.cs index e44d4d9867..ae561f73e3 100644 --- a/src/modules/colorPicker/ColorPickerUI/Helpers/NativeEventWaiter.cs +++ b/src/modules/colorPicker/ColorPickerUI/Helpers/NativeEventWaiter.cs @@ -19,7 +19,7 @@ namespace ColorPicker.Helpers public NativeEventWaiter(AppStateHandler appStateHandler) { _appStateHandler = appStateHandler; - WaitForEventLoop(Constants.ShowColorPickerSharedEvent(), _appStateHandler.ShowColorPicker); + WaitForEventLoop(Constants.ShowColorPickerSharedEvent(), _appStateHandler.StartUserSession); } public static void WaitForEventLoop(string eventName, Action callback) diff --git a/src/modules/colorPicker/ColorPickerUI/Helpers/SessionEventHelper.cs b/src/modules/colorPicker/ColorPickerUI/Helpers/SessionEventHelper.cs new file mode 100644 index 0000000000..da21c094de --- /dev/null +++ b/src/modules/colorPicker/ColorPickerUI/Helpers/SessionEventHelper.cs @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using ColorPicker.Telemetry; +using Microsoft.PowerToys.Settings.UI.Library.Enumerations; +using Microsoft.PowerToys.Telemetry; + +namespace ColorPicker.Helpers +{ + public static class SessionEventHelper + { + public static ColorPickerSession Event { get; private set; } + + public static void Start(ColorPickerActivationAction startedAs) + { + Event = new ColorPickerSession(); + Event.StartedAs = startedAs.ToString(); + _startTime = DateTime.Now; + } + + public static void End() + { + if (_startTime == null) + { + Logger.LogError("Failed to send ColorPickerSessionEvent"); + return; + } + + var duration = DateTime.Now - _startTime.Value; + Event.Duration = duration.Seconds + (duration.Milliseconds == 0 ? 0 : 1); + _startTime = null; + PowerToysTelemetry.Log.WriteEvent(Event); + } + + private static DateTime? _startTime; + } +} diff --git a/src/modules/colorPicker/ColorPickerUI/Helpers/ZoomWindowHelper.cs b/src/modules/colorPicker/ColorPickerUI/Helpers/ZoomWindowHelper.cs index e36897c25a..ffd61da6ff 100644 --- a/src/modules/colorPicker/ColorPickerUI/Helpers/ZoomWindowHelper.cs +++ b/src/modules/colorPicker/ColorPickerUI/Helpers/ZoomWindowHelper.cs @@ -179,7 +179,7 @@ namespace ColorPicker.Helpers { _zoomWindow.Left = _lastLeft + 1; _zoomWindow.Top = _lastTop + 1; - PowerToysTelemetry.Log.WriteEvent(new ColorPickerZoomOpenedEvent()); + SessionEventHelper.Event.ZoomUsed = true; } _throttledActionInvoker.ScheduleAction( diff --git a/src/modules/colorPicker/ColorPickerUI/Keyboard/KeyboardMonitor.cs b/src/modules/colorPicker/ColorPickerUI/Keyboard/KeyboardMonitor.cs index cea895c2d4..f16423d00c 100644 --- a/src/modules/colorPicker/ColorPickerUI/Keyboard/KeyboardMonitor.cs +++ b/src/modules/colorPicker/ColorPickerUI/Keyboard/KeyboardMonitor.cs @@ -72,16 +72,7 @@ namespace ColorPicker.Keyboard // ESC pressed if (virtualCode == KeyInterop.VirtualKeyFromKey(Key.Escape)) { - if (_appStateHandler.IsColorPickerEditorVisible()) - { - _appStateHandler.HideColorPickerEditor(); - } - else - { - _appStateHandler.HideColorPicker(); - PowerToysTelemetry.Log.WriteEvent(new ColorPickerCancelledEvent()); - } - + _appStateHandler.EndUserSession(); return; } @@ -114,14 +105,7 @@ namespace ColorPicker.Keyboard if (!_activationShortcutPressed) { _activationShortcutPressed = true; - if (_userSettings.ActivationAction.Value == ColorPickerActivationAction.OpenEditor) - { - _appStateHandler.ShowColorPickerEditor(); - } - else - { - _appStateHandler.ShowColorPicker(); - } + _appStateHandler.StartUserSession(); } } } diff --git a/src/modules/colorPicker/ColorPickerUI/Telemetry/ColorPickerCancelledEvent.cs b/src/modules/colorPicker/ColorPickerUI/Telemetry/ColorPickerCancelledEvent.cs deleted file mode 100644 index 00d6bdba22..0000000000 --- a/src/modules/colorPicker/ColorPickerUI/Telemetry/ColorPickerCancelledEvent.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Microsoft Corporation -// The Microsoft Corporation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Diagnostics.Tracing; -using Microsoft.PowerToys.Telemetry; -using Microsoft.PowerToys.Telemetry.Events; - -namespace ColorPicker.Telemetry -{ - [EventData] - public class ColorPickerCancelledEvent : EventBase, IEvent - { - public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage; - } -} diff --git a/src/modules/colorPicker/ColorPickerUI/Telemetry/ColorPickerSession.cs b/src/modules/colorPicker/ColorPickerUI/Telemetry/ColorPickerSession.cs new file mode 100644 index 0000000000..6f1de4d3a4 --- /dev/null +++ b/src/modules/colorPicker/ColorPickerUI/Telemetry/ColorPickerSession.cs @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Diagnostics.Tracing; +using Microsoft.PowerToys.Telemetry; +using Microsoft.PowerToys.Telemetry.Events; + +namespace ColorPicker.Telemetry +{ + [EventData] + public class ColorPickerSession : EventBase, IEvent + { + public string StartedAs { get; set; } + + public bool ZoomUsed { get; set; } + + public bool EditorOpened { get; set; } + + public bool EditorColorPickerOpened { get; set; } + + public bool EditorAdjustColorOpened { get; set; } + + public bool EditorColorAdjusted { get; set; } + + public bool EditorSimilarColorPicked { get; set; } + + public bool EditorHistoryColorPicked { get; set; } + + public bool EditorHistoryColorRemoved { get; set; } + + public bool EditorColorCopiedToClipboard { get; set; } + + public int Duration { get; set; } + + public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage; + } +} diff --git a/src/modules/colorPicker/ColorPickerUI/Telemetry/ColorPickerShowEvent.cs b/src/modules/colorPicker/ColorPickerUI/Telemetry/ColorPickerShowEvent.cs deleted file mode 100644 index 099de5972d..0000000000 --- a/src/modules/colorPicker/ColorPickerUI/Telemetry/ColorPickerShowEvent.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Microsoft Corporation -// The Microsoft Corporation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Diagnostics.Tracing; -using Microsoft.PowerToys.Telemetry; -using Microsoft.PowerToys.Telemetry.Events; - -namespace ColorPicker.Telemetry -{ - [EventData] - public class ColorPickerShowEvent : EventBase, IEvent - { - public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage; - } -} diff --git a/src/modules/colorPicker/ColorPickerUI/Telemetry/ColorPickerZoomOpenedEvent.cs b/src/modules/colorPicker/ColorPickerUI/Telemetry/ColorPickerZoomOpenedEvent.cs deleted file mode 100644 index 29477fbc17..0000000000 --- a/src/modules/colorPicker/ColorPickerUI/Telemetry/ColorPickerZoomOpenedEvent.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Microsoft Corporation -// The Microsoft Corporation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Diagnostics.Tracing; -using Microsoft.PowerToys.Telemetry; -using Microsoft.PowerToys.Telemetry.Events; - -namespace ColorPicker.Telemetry -{ - [EventData] - public class ColorPickerZoomOpenedEvent : EventBase, IEvent - { - public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage; - } -} diff --git a/src/modules/colorPicker/ColorPickerUI/ViewModels/ColorEditorViewModel.cs b/src/modules/colorPicker/ColorPickerUI/ViewModels/ColorEditorViewModel.cs index 30c59954de..f72c2adc82 100644 --- a/src/modules/colorPicker/ColorPickerUI/ViewModels/ColorEditorViewModel.cs +++ b/src/modules/colorPicker/ColorPickerUI/ViewModels/ColorEditorViewModel.cs @@ -134,6 +134,7 @@ namespace ColorPicker.ViewModels var indexToSelect = SelectedColorIndex == ColorsHistory.Count - 1 ? ColorsHistory.Count - 2 : SelectedColorIndex; ColorsHistory.RemoveAt(SelectedColorIndex); SelectedColorIndex = indexToSelect; + SessionEventHelper.Event.EditorHistoryColorRemoved = true; } private void SetupAllColorRepresentations() diff --git a/src/modules/colorPicker/ColorPickerUI/ViewModels/MainViewModel.cs b/src/modules/colorPicker/ColorPickerUI/ViewModels/MainViewModel.cs index 23bd9cc30f..fca7ca271c 100644 --- a/src/modules/colorPicker/ColorPickerUI/ViewModels/MainViewModel.cs +++ b/src/modules/colorPicker/ColorPickerUI/ViewModels/MainViewModel.cs @@ -140,14 +140,7 @@ namespace ColorPicker.ViewModels _userSettings.ColorHistory.RemoveAt(_userSettings.ColorHistory.Count - 1); } - _appStateHandler.HideColorPicker(); - - if (_userSettings.ActivationAction.Value == ColorPickerActivationAction.OpenColorPickerAndThenEditor || _userSettings.ActivationAction.Value == ColorPickerActivationAction.OpenEditor) - { - _appStateHandler.ShowColorPickerEditor(); - } - - PowerToysTelemetry.Log.WriteEvent(new ColorPickerShowEvent()); + _appStateHandler.OnColorPickerMouseDown(); } private string GetColorString() diff --git a/src/modules/colorPicker/ColorPickerUI/Views/ColorEditorView.xaml b/src/modules/colorPicker/ColorPickerUI/Views/ColorEditorView.xaml index d4eb63c0a7..94b33c40e7 100644 --- a/src/modules/colorPicker/ColorPickerUI/Views/ColorEditorView.xaml +++ b/src/modules/colorPicker/ColorPickerUI/Views/ColorEditorView.xaml @@ -20,13 +20,16 @@ - + ItemContainerStyle="{DynamicResource ColorHistoryListViewStyle}" + IsItemClickEnabled="True" + ItemClick="HistoryColors_ItemClick"> - + - +