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
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. // The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. // 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;
using System.Windows.Controls; using ColorPicker.Helpers;
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;
namespace ColorPicker namespace ColorPicker
{ {
@@ -23,16 +12,19 @@ namespace ColorPicker
/// </summary> /// </summary>
public partial class ColorEditorWindow : Window public partial class ColorEditorWindow : Window
{ {
public ColorEditorWindow() private readonly AppStateHandler _appStateHandler;
public ColorEditorWindow(AppStateHandler appStateHandler)
{ {
InitializeComponent(); InitializeComponent();
_appStateHandler = appStateHandler;
Closing += ColorEditorWindow_Closing; Closing += ColorEditorWindow_Closing;
} }
private void ColorEditorWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e) private void ColorEditorWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{ {
e.Cancel = true; e.Cancel = true;
this.Hide(); _appStateHandler.EndUserSession();
} }
} }
} }

View File

@@ -56,6 +56,7 @@ namespace ColorPicker.Controls
private void CopyToClipboardButton_Click(object sender, RoutedEventArgs e) private void CopyToClipboardButton_Click(object sender, RoutedEventArgs e)
{ {
ClipboardHelper.CopyToClipboard(ColorTextRepresentationTextBlock.Text); ClipboardHelper.CopyToClipboard(ColorTextRepresentationTextBlock.Text);
SessionEventHelper.Event.EditorColorCopiedToClipboard = true;
if (!_copyIndicatorVisible) if (!_copyIndicatorVisible)
{ {
AppearCopiedIndicator(); AppearCopiedIndicator();

View File

@@ -205,6 +205,7 @@ namespace ColorPicker.Controls
detailsStackPanel.BeginAnimation(StackPanel.OpacityProperty, opacityAppear); detailsStackPanel.BeginAnimation(StackPanel.OpacityProperty, opacityAppear);
detailsGrid.BeginAnimation(Grid.HeightProperty, resize); detailsGrid.BeginAnimation(Grid.HeightProperty, resize);
CurrentColorButton.IsEnabled = false; CurrentColorButton.IsEnabled = false;
SessionEventHelper.Event.EditorAdjustColorOpened = true;
} }
} }
@@ -239,8 +240,8 @@ namespace ColorPicker.Controls
private void OKButton_Click(object sender, RoutedEventArgs e) private void OKButton_Click(object sender, RoutedEventArgs e)
{ {
HideDetails(); HideDetails();
SelectedColorChangedCommand.Execute(_currentColor); SelectedColorChangedCommand.Execute(_currentColor);
SessionEventHelper.Event.EditorColorAdjusted = true;
} }
private void CancelButton_Click(object sender, RoutedEventArgs e) private void CancelButton_Click(object sender, RoutedEventArgs e)
@@ -258,6 +259,7 @@ namespace ColorPicker.Controls
{ {
var selectedColor = ((SolidColorBrush)((Button)sender).Background).Color; var selectedColor = ((SolidColorBrush)((Button)sender).Background).Color;
SelectedColorChangedCommand.Execute(selectedColor); SelectedColorChangedCommand.Execute(selectedColor);
SessionEventHelper.Event.EditorSimilarColorPicked = true;
} }
private void ValueGradientGrid_MouseMove(object sender, MouseEventArgs e) private void ValueGradientGrid_MouseMove(object sender, MouseEventArgs e)

View File

@@ -5,7 +5,9 @@
using System; using System;
using System.ComponentModel.Composition; using System.ComponentModel.Composition;
using System.Windows; using System.Windows;
using ColorPicker.Settings;
using ColorPicker.ViewModelContracts; using ColorPicker.ViewModelContracts;
using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
namespace ColorPicker.Helpers namespace ColorPicker.Helpers
{ {
@@ -13,15 +15,17 @@ namespace ColorPicker.Helpers
public class AppStateHandler public class AppStateHandler
{ {
private readonly IColorEditorViewModel _colorEditorViewModel; private readonly IColorEditorViewModel _colorEditorViewModel;
private readonly IUserSettings _userSettings;
private ColorEditorWindow _colorEditorWindow; private ColorEditorWindow _colorEditorWindow;
private bool _colorPickerShown; private bool _colorPickerShown;
private object _colorPickerVisibilityLock = new object(); private object _colorPickerVisibilityLock = new object();
[ImportingConstructor] [ImportingConstructor]
public AppStateHandler(IColorEditorViewModel colorEditorViewModel) public AppStateHandler(IColorEditorViewModel colorEditorViewModel, IUserSettings userSettings)
{ {
Application.Current.MainWindow.Closed += MainWindow_Closed; Application.Current.MainWindow.Closed += MainWindow_Closed;
_colorEditorViewModel = colorEditorViewModel; _colorEditorViewModel = colorEditorViewModel;
_userSettings = userSettings;
} }
public event EventHandler AppShown; public event EventHandler AppShown;
@@ -30,48 +34,110 @@ namespace ColorPicker.Helpers
public event EventHandler AppClosed; public event EventHandler AppClosed;
public void ShowColorPicker() public void StartUserSession()
{ {
lock (_colorPickerVisibilityLock) lock (_colorPickerVisibilityLock)
{ {
if (!_colorPickerShown) if (!_colorPickerShown && !IsColorPickerEditorVisible())
{ {
AppShown?.Invoke(this, EventArgs.Empty); SessionEventHelper.Start(_userSettings.ActivationAction.Value);
Application.Current.MainWindow.Opacity = 0; }
Application.Current.MainWindow.Visibility = Visibility.Visible;
_colorPickerShown = true; if (_userSettings.ActivationAction.Value == ColorPickerActivationAction.OpenEditor)
{
ShowColorPickerEditor();
}
else
{
ShowColorPicker();
} }
} }
} }
public void HideColorPicker() public void EndUserSession()
{ {
lock (_colorPickerVisibilityLock) lock (_colorPickerVisibilityLock)
{ {
if (_colorPickerShown) if (IsColorPickerEditorVisible() || _colorPickerShown)
{ {
Application.Current.MainWindow.Opacity = 0; if (IsColorPickerEditorVisible())
Application.Current.MainWindow.Visibility = Visibility.Collapsed; {
AppHidden?.Invoke(this, EventArgs.Empty); HideColorPickerEditor();
_colorPickerShown = false; }
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) if (_colorEditorWindow == null)
{ {
_colorEditorWindow = new ColorEditorWindow(); _colorEditorWindow = new ColorEditorWindow(this);
_colorEditorWindow.Content = _colorEditorViewModel; _colorEditorWindow.Content = _colorEditorViewModel;
_colorEditorViewModel.OpenColorPickerRequested += ColorEditorViewModel_OpenColorPickerRequested; _colorEditorViewModel.OpenColorPickerRequested += ColorEditorViewModel_OpenColorPickerRequested;
_colorEditorViewModel.OpenColorPickerRequested += (object sender, EventArgs e) =>
{
SessionEventHelper.Event.EditorColorPickerOpened = true;
};
} }
_colorEditorViewModel.Initialize(); _colorEditorViewModel.Initialize();
_colorEditorWindow.Show(); _colorEditorWindow.Show();
SessionEventHelper.Event.EditorOpened = true;
} }
public void HideColorPickerEditor() private void HideColorPickerEditor()
{ {
if (_colorEditorWindow != null) if (_colorEditorWindow != null)
{ {
@@ -79,7 +145,7 @@ namespace ColorPicker.Helpers
} }
} }
public bool IsColorPickerEditorVisible() private bool IsColorPickerEditorVisible()
{ {
if (_colorEditorWindow != null) if (_colorEditorWindow != null)
{ {
@@ -90,12 +156,6 @@ namespace ColorPicker.Helpers
return false; return false;
} }
public static void SetTopMost()
{
Application.Current.MainWindow.Topmost = false;
Application.Current.MainWindow.Topmost = true;
}
private void MainWindow_Closed(object sender, EventArgs e) private void MainWindow_Closed(object sender, EventArgs e)
{ {
AppClosed?.Invoke(this, EventArgs.Empty); AppClosed?.Invoke(this, EventArgs.Empty);
@@ -103,7 +163,11 @@ namespace ColorPicker.Helpers
private void ColorEditorViewModel_OpenColorPickerRequested(object sender, EventArgs e) private void ColorEditorViewModel_OpenColorPickerRequested(object sender, EventArgs e)
{ {
ShowColorPicker(); lock (_colorPickerVisibilityLock)
{
ShowColorPicker();
}
_colorEditorWindow.Hide(); _colorEditorWindow.Hide();
} }
} }

View File

@@ -19,7 +19,7 @@ namespace ColorPicker.Helpers
public NativeEventWaiter(AppStateHandler appStateHandler) public NativeEventWaiter(AppStateHandler appStateHandler)
{ {
_appStateHandler = appStateHandler; _appStateHandler = appStateHandler;
WaitForEventLoop(Constants.ShowColorPickerSharedEvent(), _appStateHandler.ShowColorPicker); WaitForEventLoop(Constants.ShowColorPickerSharedEvent(), _appStateHandler.StartUserSession);
} }
public static void WaitForEventLoop(string eventName, Action callback) 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.Left = _lastLeft + 1;
_zoomWindow.Top = _lastTop + 1; _zoomWindow.Top = _lastTop + 1;
PowerToysTelemetry.Log.WriteEvent(new ColorPickerZoomOpenedEvent()); SessionEventHelper.Event.ZoomUsed = true;
} }
_throttledActionInvoker.ScheduleAction( _throttledActionInvoker.ScheduleAction(

View File

@@ -72,16 +72,7 @@ namespace ColorPicker.Keyboard
// ESC pressed // ESC pressed
if (virtualCode == KeyInterop.VirtualKeyFromKey(Key.Escape)) if (virtualCode == KeyInterop.VirtualKeyFromKey(Key.Escape))
{ {
if (_appStateHandler.IsColorPickerEditorVisible()) _appStateHandler.EndUserSession();
{
_appStateHandler.HideColorPickerEditor();
}
else
{
_appStateHandler.HideColorPicker();
PowerToysTelemetry.Log.WriteEvent(new ColorPickerCancelledEvent());
}
return; return;
} }
@@ -114,14 +105,7 @@ namespace ColorPicker.Keyboard
if (!_activationShortcutPressed) if (!_activationShortcutPressed)
{ {
_activationShortcutPressed = true; _activationShortcutPressed = true;
if (_userSettings.ActivationAction.Value == ColorPickerActivationAction.OpenEditor) _appStateHandler.StartUserSession();
{
_appStateHandler.ShowColorPickerEditor();
}
else
{
_appStateHandler.ShowColorPicker();
}
} }
} }
} }

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; var indexToSelect = SelectedColorIndex == ColorsHistory.Count - 1 ? ColorsHistory.Count - 2 : SelectedColorIndex;
ColorsHistory.RemoveAt(SelectedColorIndex); ColorsHistory.RemoveAt(SelectedColorIndex);
SelectedColorIndex = indexToSelect; SelectedColorIndex = indexToSelect;
SessionEventHelper.Event.EditorHistoryColorRemoved = true;
} }
private void SetupAllColorRepresentations() private void SetupAllColorRepresentations()

View File

@@ -140,14 +140,7 @@ namespace ColorPicker.ViewModels
_userSettings.ColorHistory.RemoveAt(_userSettings.ColorHistory.Count - 1); _userSettings.ColorHistory.RemoveAt(_userSettings.ColorHistory.Count - 1);
} }
_appStateHandler.HideColorPicker(); _appStateHandler.OnColorPickerMouseDown();
if (_userSettings.ActivationAction.Value == ColorPickerActivationAction.OpenColorPickerAndThenEditor || _userSettings.ActivationAction.Value == ColorPickerActivationAction.OpenEditor)
{
_appStateHandler.ShowColorPickerEditor();
}
PowerToysTelemetry.Log.WriteEvent(new ColorPickerShowEvent());
} }
private string GetColorString() private string GetColorString()

View File

@@ -20,13 +20,16 @@
<!-- Side bar --> <!-- Side bar -->
<Grid Background="{DynamicResource SecondaryBackgroundBrush}"> <Grid Background="{DynamicResource SecondaryBackgroundBrush}">
<ui:ListView Margin="0,48,0,0" <ui:ListView x:Name="HistoryColors"
Margin="0,48,0,0"
Grid.Row="1" Grid.Row="1"
Padding="0" Padding="0"
TabIndex="3" TabIndex="3"
ItemsSource="{Binding ColorsHistory}" ItemsSource="{Binding ColorsHistory}"
SelectedIndex="{Binding SelectedColorIndex}" SelectedIndex="{Binding SelectedColorIndex}"
ItemContainerStyle="{DynamicResource ColorHistoryListViewStyle}"> ItemContainerStyle="{DynamicResource ColorHistoryListViewStyle}"
IsItemClickEnabled="True"
ItemClick="HistoryColors_ItemClick">
<ui:ListView.ContextMenu> <ui:ListView.ContextMenu>
<ContextMenu Visibility="{Binding ColorsHistory.Count, Converter={StaticResource numberToVisibilityConverter}}"> <ContextMenu Visibility="{Binding ColorsHistory.Count, Converter={StaticResource numberToVisibilityConverter}}">
<MenuItem Header="{x:Static p:Resources.Remove}" <MenuItem Header="{x:Static p:Resources.Remove}"

View File

@@ -2,20 +2,8 @@
// The Microsoft Corporation licenses this file to you under the MIT license. // The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. // 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.Controls;
using System.Windows.Data; using ColorPicker.Helpers;
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;
namespace ColorPicker.Views namespace ColorPicker.Views
{ {
@@ -26,5 +14,12 @@ namespace ColorPicker.Views
{ {
public ColorEditorView() => public ColorEditorView() =>
InitializeComponent(); 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;
}
} }
} }