Skip to content

Commit

Permalink
Merge pull request #144 from JasonWei512/feature/today-coding-time-de…
Browse files Browse the repository at this point in the history
…velop

Display "total time today" in status bar
  • Loading branch information
alanhamlett authored May 23, 2023
2 parents ac15d7a + c212560 commit 779e2e9
Show file tree
Hide file tree
Showing 13 changed files with 566 additions and 8 deletions.
9 changes: 7 additions & 2 deletions Dev14/Dev14.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
<ItemGroup>
<Compile Include="ExtensionUtils\GuidList2015.cs" />
<Compile Include="ExtensionUtils\Logger.cs" />
<Compile Include="ExtensionUtils\StatusbarControl.cs" />
<Compile Include="ExtensionUtils\StatusbarInjector.cs" />
<Compile Include="Forms\ApiKeyForm.cs">
<SubType>Form</SubType>
</Compile>
Expand Down Expand Up @@ -175,12 +177,15 @@
<Reference Include="stdole, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<EmbedInteropTypes>False</EmbedInteropTypes>
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="System" />
<Reference Include="System.Design" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="WakaTime.Shared.ExtensionUtils, Version=4.0.0.0, Culture=neutral, PublicKeyToken=202d1174b8524eea, processorArchitecture=MSIL">
<HintPath>..\packages\WakaTime.Shared.ExtensionUtils.4.0.0\lib\netstandard2.0\WakaTime.Shared.ExtensionUtils.dll</HintPath>
<Reference Include="WindowsBase" />
<Reference Include="WakaTime.Shared.ExtensionUtils, Version=4.2.0.0, Culture=neutral, PublicKeyToken=202d1174b8524eea, processorArchitecture=MSIL">
<HintPath>..\packages\WakaTime.Shared.ExtensionUtils.4.2.0\lib\netstandard2.0\WakaTime.Shared.ExtensionUtils.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
Expand Down
57 changes: 57 additions & 0 deletions Dev14/ExtensionUtils/StatusbarControl.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using Microsoft.VisualStudio.Shell;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace WakaTime.ExtensionUtils
{
internal class StatusbarControl : TextBlock
{
private const string Icon = "🕑";

private readonly Brush _normalBackground = new SolidColorBrush(Colors.Transparent);
private readonly Brush _hoverBackground = new SolidColorBrush(Colors.White) { Opacity = 0.2 };

public StatusbarControl()
{
Text = Icon;
Foreground = new SolidColorBrush(Colors.White);
Background = _normalBackground;

VerticalAlignment = VerticalAlignment.Center;
Margin = new Thickness(7, 0, 7, 0);
Padding = new Thickness(7, 0, 7, 0);

MouseEnter += (s, e) =>
{
Cursor = Cursors.Hand;
Background = _hoverBackground;
};

MouseLeave += (s, e) =>
{
Cursor = Cursors.Arrow;
Background = _normalBackground;
};

MouseLeftButtonUp += (s, e) =>
{
// Open WakaTime in browser
System.Diagnostics.Process.Start("https://wakatime.com/");
};
}

public void SetText(string text)
{
ThreadHelper.ThrowIfNotOnUIThread();
Text = string.IsNullOrEmpty(text) ? Icon : $"{Icon} {text}";
}

public void SetToolTip(string toolTip)
{
ThreadHelper.ThrowIfNotOnUIThread();
ToolTip = toolTip;
}
}
}
87 changes: 87 additions & 0 deletions Dev14/ExtensionUtils/StatusbarInjector.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using Microsoft.VisualStudio.Shell;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using Task = System.Threading.Tasks.Task;

namespace WakaTime.ExtensionUtils
{
internal static class StatusbarInjector
{
private static Panel _panel;

private static DependencyObject FindChild(DependencyObject parent, string childName)
{
if (parent == null)
{
return null;
}

int childrenCount = VisualTreeHelper.GetChildrenCount(parent);

for (int i = 0; i < childrenCount; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, i);

if (child is FrameworkElement frameworkElement && frameworkElement.Name == childName)
{
return frameworkElement;
}

child = FindChild(child, childName);

if (child != null)
{
return child;
}
}

return null;
}

private static async Task EnsureUIAsync()
{
while (_panel is null)
{
_panel = FindChild(Application.Current.MainWindow, "StatusBarPanel") as DockPanel;
if (_panel is null)
{
// Start window is showing. Need to wait for status bar render.
await Task.Delay(5000);
}
}
}

public static async Task InjectControlAsync(FrameworkElement element)
{
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
await EnsureUIAsync();

// Place the element to the left of all elements on the right side of the status bar
element.SetValue(DockPanel.DockProperty, Dock.Right);
int index = GetLastDockRightElementIndex(_panel.Children) + 1;
_panel.Children.Insert(index, element);
}

private static int GetLastDockRightElementIndex(UIElementCollection elements)
{
int lastDockRightElementIndex = 0;

int elementCount = elements.Count;
for (int i = 0; i < elementCount; i++)
{
object element = elements[i];

if (element is DependencyObject dependencyObject &&
dependencyObject.GetValue(DockPanel.DockProperty) is Dock dockProperty &&
dockProperty == Dock.Right)
{
lastDockRightElementIndex = i;
}
}

return lastDockRightElementIndex;
}
}
}
39 changes: 38 additions & 1 deletion Dev14/WakaTimePackage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public sealed class WakaTimePackage : AsyncPackage
private SettingsForm _settingsForm;
private bool _isBuildRunning;
private string _solutionName;
private StatusbarControl _statusbarControl;

/// <summary>
/// Initialization of the package; this method is called right after the package is sited, so this is the place
Expand Down Expand Up @@ -95,12 +96,24 @@ private async Task InitializeAsync(CancellationToken cancellationToken)

try
{
await _wakatime.InitializeAsync();
// Initialize _wakatime in background, which may take several seconds
Task wakaTimeInitializationTask = _wakatime.InitializeAsync();

// When initialized asynchronously, the current thread may be a background thread at this point.
// Do any initialization that requires the UI thread after switching to the UI thread.
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);

// Inject control to status bar
_statusbarControl = new StatusbarControl();
_statusbarControl.SetText("Initializing...");
_statusbarControl.SetToolTip("WakaTime: Initializing...");
await StatusbarInjector.InjectControlAsync(_statusbarControl);

// Wait for _wakatime to complete initialization,and display today's coding time on status bar
await wakaTimeInitializationTask;
UpdateTimeOnStatusbarControl(_wakatime.TotalTimeToday, _wakatime.TotalTimeTodayDetailed);
_wakatime.TotalTimeTodayUpdated += WakatimeTotalTimeTodayUpdated;

// Visual Studio Events
_docEvents = _dte.Events.DocumentEvents;
_windowEvents = _dte.Events.WindowEvents;
Expand Down Expand Up @@ -380,6 +393,30 @@ private void TextEditorEventsLineChanged(TextPoint startPoint, TextPoint endPoin
_logger.Error("TextEditorEventsLineChanged", ex);
}
}

private void WakatimeTotalTimeTodayUpdated(object sender, TotalTimeTodayUpdatedEventArgs e)
{
_ = JoinableTaskFactory.RunAsync(async () =>
{
await JoinableTaskFactory.SwitchToMainThreadAsync();
UpdateTimeOnStatusbarControl(e.TotalTimeToday, e.TotalTimeTodayDetailed);
});
}

private void UpdateTimeOnStatusbarControl(string totalTimeToday, string totalTimeTodayDetailed)
{
ThreadHelper.ThrowIfNotOnUIThread();

string text = string.IsNullOrEmpty(totalTimeToday) ? "WakaTime" : totalTimeToday;
_statusbarControl?.SetText(text);

string toolTip = "WakaTime: Today's coding time";
if (!string.IsNullOrEmpty(totalTimeTodayDetailed))
{
toolTip += Environment.NewLine + totalTimeTodayDetailed;
}
_statusbarControl?.SetToolTip(toolTip);
}
}

internal static class CoreAssembly
Expand Down
2 changes: 1 addition & 1 deletion Dev14/packages.config
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@
<package id="Microsoft.VisualStudio.Utilities" version="14.3.25407" targetFramework="net48" />
<package id="Microsoft.VisualStudio.Validation" version="14.1.111" targetFramework="net48" />
<package id="Microsoft.VSSDK.BuildTools" version="14.3.25420" targetFramework="net48" developmentDependency="true" />
<package id="WakaTime.Shared.ExtensionUtils" version="4.0.0" targetFramework="net48" />
<package id="WakaTime.Shared.ExtensionUtils" version="4.2.0" targetFramework="net48" />
</packages>
7 changes: 6 additions & 1 deletion Dev16/Dev16.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@
</PropertyGroup>
<ItemGroup>
<Compile Include="ExtensionUtils\Logger.cs" />
<Compile Include="ExtensionUtils\StatusbarControl.cs" />
<Compile Include="ExtensionUtils\StatusbarInjector.cs" />
<Compile Include="Forms\ApiKeyForm.cs">
<SubType>Form</SubType>
</Compile>
Expand Down Expand Up @@ -93,7 +95,7 @@
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="WakaTime.Shared.ExtensionUtils">
<Version>4.0.0</Version>
<Version>4.2.0</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>
Expand All @@ -118,12 +120,15 @@
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="System" />
<Reference Include="System.Design" />
<Reference Include="System.Drawing" />
<Reference Include="System.IO.Compression.FileSystem" />
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Windows.Forms" />
<Reference Include="WindowsBase" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="'$(VSToolsPath)' != ''" />
Expand Down
57 changes: 57 additions & 0 deletions Dev16/ExtensionUtils/StatusbarControl.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using Microsoft.VisualStudio.Shell;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace WakaTime.ExtensionUtils
{
internal class StatusbarControl : TextBlock
{
private const string Icon = "🕑";

private readonly Brush _normalBackground = new SolidColorBrush(Colors.Transparent);
private readonly Brush _hoverBackground = new SolidColorBrush(Colors.White) { Opacity = 0.2 };

public StatusbarControl()
{
Text = Icon;
Foreground = new SolidColorBrush(Colors.White);
Background = _normalBackground;

VerticalAlignment = VerticalAlignment.Center;
Margin = new Thickness(7, 0, 7, 0);
Padding = new Thickness(7, 0, 7, 0);

MouseEnter += (s, e) =>
{
Cursor = Cursors.Hand;
Background = _hoverBackground;
};

MouseLeave += (s, e) =>
{
Cursor = Cursors.Arrow;
Background = _normalBackground;
};

MouseLeftButtonUp += (s, e) =>
{
// Open WakaTime in browser
System.Diagnostics.Process.Start("https://wakatime.com/");
};
}

public void SetText(string text)
{
ThreadHelper.ThrowIfNotOnUIThread();
Text = string.IsNullOrEmpty(text) ? Icon : $"{Icon} {text}";
}

public void SetToolTip(string toolTip)
{
ThreadHelper.ThrowIfNotOnUIThread();
ToolTip = toolTip;
}
}
}
Loading

0 comments on commit 779e2e9

Please sign in to comment.