Skip to content

Commit

Permalink
Fixed a bug that can allow multiple instances to run in the backgroun…
Browse files Browse the repository at this point in the history
…d, and added buttons to toast notifications.
  • Loading branch information
leonzhou-smokeball committed Dec 18, 2024
1 parent 40024a1 commit 17daacd
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 49 deletions.
6 changes: 6 additions & 0 deletions App/App.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@
<SupportedOSPlatformVersion>10.0.22000.0</SupportedOSPlatformVersion>
<ApplicationHighDpiMode>PerMonitorV2</ApplicationHighDpiMode>
<Platforms>AnyCPU;x64;ARM64;x86</Platforms>
<PackageVersion>2.1.1</PackageVersion>
<PackageProjectUrl>https://github.com/soleon/Percentage</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/soleon/Percentage?tab=MIT-1-ov-file</PackageLicenseUrl>
<PackageIcon>Icon.png</PackageIcon>
<RepositoryUrl>https://github.com/soleon/Percentage</RepositoryUrl>
<RepositoryType>git</RepositoryType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Codify.System.Windows" Version="*" />
Expand Down
3 changes: 1 addition & 2 deletions App/App.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
StartupUri="TrayIconWindow.xaml"
ShutdownMode="OnExplicitShutdown">
StartupUri="TrayIconWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
Expand Down
34 changes: 33 additions & 1 deletion App/App.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using Microsoft.Toolkit.Uwp.Notifications;
using Percentage.App.Extensions;
using Percentage.App.Pages;
using Wpf.Ui;
using Wpf.Ui.Markup;
using static Percentage.App.Properties.Settings;
Expand Down Expand Up @@ -42,7 +46,13 @@ public App()
{
_appMutex = new Mutex(true, Id, out var isNewInstance);

if (!isNewInstance) Shutdown(1);
if (!isNewInstance)
{
Shutdown(1);
return;
}

ShutdownMode = ShutdownMode.OnExplicitShutdown;

DispatcherUnhandledException += (_, e) => HandleException(e.Exception);

Expand All @@ -54,6 +64,28 @@ public App()

// User settings migration for backward compatibility.
MigrateUserSettings();

// Subscribe to toast notification activations.
ToastNotificationManagerCompat.OnActivated += async toastArgs =>
{
if (ToastArguments.Parse(toastArgs.Argument).GetActionArgument() ==
ToastNotificationExtensions.Action.ViewDetails)
await Dispatcher.InvokeAsync(() => ActivateMainWindow().NavigateToPage<DetailsPage>());
};
}

internal static MainWindow ActivateMainWindow()
{
var window = Current.Windows.OfType<MainWindow>().FirstOrDefault();
if (window != null)
{
window.Activate();
return window;
}

window = new MainWindow();
window.Show();
return window;
}

internal static Exception GetTrayIconUpdateError()
Expand Down
29 changes: 29 additions & 0 deletions App/Extensions/ToastNotificationExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Microsoft.Toolkit.Uwp.Notifications;

namespace Percentage.App.Extensions;

internal static class ToastNotificationExtensions
{
private const string ActionArgumentKey = "action";

internal static Action GetActionArgument(this ToastArguments arguments)
{
return arguments.GetEnum<Action>(ActionArgumentKey);
}

internal static void ShowToastNotification(string header, string body)
{
new ToastContentBuilder()
.AddText(header)
.AddText(body)
.AddButton(new ToastButton().SetContent("See more details")
.AddArgument(ActionArgumentKey, Action.ViewDetails))
.AddButton(new ToastButtonDismiss())
.Show();
}

internal enum Action
{
ViewDetails = 0
}
}
10 changes: 0 additions & 10 deletions App/NotificationType.cs

This file was deleted.

54 changes: 20 additions & 34 deletions App/TrayIconWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.ComponentModel;
using System.Linq;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Windows;
Expand All @@ -10,8 +9,8 @@
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using Windows.Devices.Power;
using Microsoft.Toolkit.Uwp.Notifications;
using Microsoft.Win32;
using Percentage.App.Extensions;
using Percentage.App.Pages;
using Wpf.Ui.Appearance;
using Wpf.Ui.Markup;
Expand Down Expand Up @@ -44,20 +43,6 @@ public TrayIconWindow()
_refreshTimer.Tick += (_, _) => _batteryStatusUpdateSubject.OnNext(false);
}

private static MainWindow ActivateMainWindow()
{
var window = Application.Current.Windows.OfType<MainWindow>().FirstOrDefault();
if (window != null)
{
window.Activate();
return window;
}

window = new MainWindow();
window.Show();
return window;
}

private static Brush GetBrushFromColourHexString(string hexString, Brush fallbackBrush)
{
object colour;
Expand Down Expand Up @@ -121,12 +106,12 @@ private Brush GetTargetBrush(bool isUsingAutoColour, string targetColour, Brush

private void OnAboutMenuItemClick(object sender, RoutedEventArgs e)
{
ActivateMainWindow().NavigateToPage<AboutPage>();
App.ActivateMainWindow().NavigateToPage<AboutPage>();
}

private void OnDetailsMenuItemClick(object sender, RoutedEventArgs e)
{
ActivateMainWindow().NavigateToPage<DetailsPage>();
App.ActivateMainWindow().NavigateToPage<DetailsPage>();
}

private void OnExitMenuItemClick(object sender, RoutedEventArgs e)
Expand All @@ -138,7 +123,7 @@ private void OnLoaded(object sender, RoutedEventArgs args)
{
Visibility = Visibility.Collapsed;

if (!Default.HideAtStartup) ActivateMainWindow().NavigateToPage<DetailsPage>();
if (!Default.HideAtStartup) App.ActivateMainWindow().NavigateToPage<DetailsPage>();

// Debounce calls to update battery status.
// This should be the only place that calls the UpdateBatteryStatus method.
Expand Down Expand Up @@ -173,12 +158,12 @@ private void OnLoaded(object sender, RoutedEventArgs args)

private void OnNotifyIconLeftDoubleClick(NotifyIcon sender, RoutedEventArgs e)
{
ActivateMainWindow().NavigateToPage<DetailsPage>();
App.ActivateMainWindow().NavigateToPage<DetailsPage>();
}

private void OnSettingsMenuItemClick(object sender, RoutedEventArgs e)
{
ActivateMainWindow().NavigateToPage<SettingsPage>();
App.ActivateMainWindow().NavigateToPage<SettingsPage>();
}

private void OnUserSettingsPropertyChanged(string propertyName)
Expand Down Expand Up @@ -401,21 +386,22 @@ void CheckAndSendNotification()
return;

var utcNow = DateTime.UtcNow;
if (_lastNotification.Type != notificationType)
// Notification required, and battery status has changed from last notification, notify user.
new ToastContentBuilder()
.AddText(_notificationTitle)
.AddText(_notificationText)
.Show();
else if (utcNow - _lastNotification.DateTime > TimeSpan.FromMinutes(5))
// Notification required, but battery status is the same as last notification for more than 5 minutes,
// notify user.
new ToastContentBuilder()
.AddText(_notificationTitle)
.AddText(_notificationText)
.Show();
if (_lastNotification.Type != notificationType ||
utcNow - _lastNotification.DateTime > TimeSpan.FromMinutes(5))
// Notification is required if the existing notification type is different from the previous one or
// battery status is the same, but it has been more than 5 minutes since the last notification was shown.
ToastNotificationExtensions.ShowToastNotification(_notificationTitle, _notificationText);

_lastNotification = (notificationType, utcNow);
}
}

private enum NotificationType : byte
{
None = 0,
Critical,
Low,
High,
Full
}
}
20 changes: 18 additions & 2 deletions Pack/Package.appxmanifest
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5"
xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10"
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap rescap">
IgnorableNamespaces="uap rescap com desktop">

<Identity
Name="61867SoleonInnovation.BatteryPercentageIcon"
Publisher="CN=B0B1FE5B-CC73-4F71-BD3F-7B809647826C"
Version="2.1.0.0" />
Version="2.1.1.0" />

<Properties>
<DisplayName>Battery Percentage Icon</DisplayName>
Expand Down Expand Up @@ -47,6 +49,20 @@
Enabled="true"
DisplayName="Battery Percentage Icon" />
</uap5:Extension>

<!--Specify which CLSID to activate when toast clicked-->
<desktop:Extension Category="windows.toastNotificationActivation">
<desktop:ToastNotificationActivation ToastActivatorCLSID="549f9494-b2ef-4e7a-89a4-f36ad71025a0" />
</desktop:Extension>

<!--Register COM CLSID LocalServer32 registry key-->
<com:Extension Category="windows.comServer">
<com:ComServer>
<com:ExeServer Executable="App\Percentage.App.exe" Arguments="-ToastActivated" DisplayName="Toast activator">
<com:Class Id="549f9494-b2ef-4e7a-89a4-f36ad71025a0" DisplayName="Toast activator"/>
</com:ExeServer>
</com:ComServer>
</com:Extension>
</Extensions>
</Application>
</Applications>
Expand Down

0 comments on commit 17daacd

Please sign in to comment.