Add telemetry to ColorPicker (#10413)

This commit is contained in:
Mykhailo Pylyp 2021-03-25 13:11:36 +02:00 committed by GitHub
parent 6229ea4559
commit 7ba03ed24f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 197 additions and 132 deletions

View File

@ -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
/// </summary>
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();
}
}
}

View File

@ -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();

View File

@ -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)

View File

@ -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();
}
}

View File

@ -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)

View File

@ -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;
}
}

View File

@ -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(

View File

@ -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();
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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()

View File

@ -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()

View File

@ -20,13 +20,16 @@
<!-- Side bar -->
<Grid Background="{DynamicResource SecondaryBackgroundBrush}">
<ui:ListView Margin="0,48,0,0"
<ui:ListView x:Name="HistoryColors"
Margin="0,48,0,0"
Grid.Row="1"
Padding="0"
TabIndex="3"
ItemsSource="{Binding ColorsHistory}"
SelectedIndex="{Binding SelectedColorIndex}"
ItemContainerStyle="{DynamicResource ColorHistoryListViewStyle}">
ItemContainerStyle="{DynamicResource ColorHistoryListViewStyle}"
IsItemClickEnabled="True"
ItemClick="HistoryColors_ItemClick">
<ui:ListView.ContextMenu>
<ContextMenu Visibility="{Binding ColorsHistory.Count, Converter={StaticResource numberToVisibilityConverter}}">
<MenuItem Header="{x:Static p:Resources.Remove}"
@ -75,7 +78,7 @@
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="0,1,0,0" />
<!-- Enable once we have settings linking available -->
<!--<Button Width="46"
Height="32"
@ -87,7 +90,7 @@
Margin="0,0,46,0"
ToolTipService.ToolTip="{x:Static p:Resources.Open_settings}"
AutomationProperties.Name="{x:Static p:Resources.Open_settings}" />-->
<Button Width="64"
Height="32"
TabIndex="1"

View File

@ -2,20 +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.Navigation;
using System.Windows.Shapes;
using ColorPicker.Helpers;
namespace ColorPicker.Views
{
@ -26,5 +14,12 @@ namespace ColorPicker.Views
{
public ColorEditorView() =>
InitializeComponent();
private void HistoryColors_ItemClick(object sender, ModernWpf.Controls.ItemClickEventArgs e)
{
// Note: it does not handle clicking on the same color.
// More appropriate event would be SelectionChanged but we can not distinguish between user action and program action inside of it.
SessionEventHelper.Event.EditorHistoryColorPicked = true;
}
}
}