Skip to content

Commit

Permalink
Removed DFAssist.WinToast project
Browse files Browse the repository at this point in the history
Added support for UWP Toast Notifications
- there are a lot more dependencies in libs, required by the uwp platform
  • Loading branch information
easly1989 committed Nov 8, 2019
1 parent 2eab7f7 commit 2fd3bf8
Show file tree
Hide file tree
Showing 26 changed files with 555 additions and 2,298 deletions.
13 changes: 12 additions & 1 deletion DFAssist.Core/DFAssist.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<RootNamespace>DFAssist.Core</RootNamespace>
<AssemblyName>DFAssist.Core</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<TargetPlatformVersion>10.0.10240.0</TargetPlatformVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
Expand Down Expand Up @@ -57,9 +58,12 @@
<Reference Include="PresentationCore" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Management" />
<Reference Include="System.Xaml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="Windows.Data" />
<Reference Include="Windows.UI" />
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
Expand All @@ -77,10 +81,17 @@
<Compile Include="Repositories\DataRepository.cs" />
<Compile Include="Repositories\LocalizationRepository.cs" />
<Compile Include="Repositories\RepositoryBase.cs" />
<Compile Include="Toast\WinToastWrapper.cs" />
<Compile Include="..\SharedAssemblyInfo.cs">
<Link>Properties\SharedAssemblyInfo.cs</Link>
</Compile>
<Compile Include="Toast\Base\DesktopNotificationManagerCompat.cs" />
<Compile Include="Toast\Base\DesktopBridgeHelpers.cs" />
<Compile Include="Toast\Base\DesktopNotificationHistoryCompat.cs" />
<Compile Include="Toast\Base\INotificationActivationCallback.cs" />
<Compile Include="Toast\Base\NotificationActivator.cs" />
<Compile Include="Toast\Base\NotificationUserInput.cs" />
<Compile Include="Toast\ToastNotificationActivator.cs" />
<Compile Include="Toast\ToastManager.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json">
Expand Down
70 changes: 70 additions & 0 deletions DFAssist.Core/Toast/Base/DesktopBridgeHelpers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************

using System;
using System.Runtime.InteropServices;
using System.Text;

namespace DFAssist.Core.Toast.Base
{
/// <summary>
/// Code from https://github.com/qmatteoq/DesktopBridgeHelpers/edit/master/DesktopBridge.Helpers/Helpers.cs
/// </summary>
public static class DesktopBridgeHelpers
{
// ReSharper disable InconsistentNaming
// ReSharper disable ArrangeTypeMemberModifiers
const long APPMODEL_ERROR_NO_PACKAGE = 15700L;
// ReSharper restore ArrangeTypeMemberModifiers
// ReSharper restore InconsistentNaming

[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern int GetCurrentPackageFullName(ref int packageFullNameLength, StringBuilder packageFullName);

private static bool? _isRunningAsUwp;
public static bool IsRunningAsUwp()
{
if (_isRunningAsUwp != null)
return _isRunningAsUwp.Value;

if (IsWindows7OrLower)
{
_isRunningAsUwp = false;
}
else
{
var length = 0;
var sb = new StringBuilder(0);
// ReSharper disable RedundantAssignment
var result = GetCurrentPackageFullName(ref length, sb);
// ReSharper restore RedundantAssignment
sb = new StringBuilder(length);
result = GetCurrentPackageFullName(ref length, sb);

_isRunningAsUwp = result != APPMODEL_ERROR_NO_PACKAGE;
}

return _isRunningAsUwp.Value;
}

private static bool IsWindows7OrLower
{
get
{
var versionMajor = Environment.OSVersion.Version.Major;
var versionMinor = Environment.OSVersion.Version.Minor;
var version = versionMajor + (double)versionMinor / 10;
return version <= 6.1;
}
}
}
}
98 changes: 98 additions & 0 deletions DFAssist.Core/Toast/Base/DesktopNotificationHistoryCompat.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************

using Windows.UI.Notifications;

namespace DFAssist.Core.Toast.Base
{
/// <summary>
/// Manages the toast notifications for an app including the ability the clear all toast history and removing individual toasts.
/// </summary>
public sealed class DesktopNotificationHistoryCompat
{
private readonly string _aumid;
private readonly ToastNotificationHistory _history;

/// <summary>
/// Do not call this. Instead, call <see cref="DesktopNotificationManagerCompat.History"/> to obtain an instance.
/// </summary>
internal DesktopNotificationHistoryCompat(string aumid)
{
_aumid = aumid;
_history = ToastNotificationManager.History;
}

/// <summary>
/// Removes all notifications sent by this app from action center.
/// </summary>
public void Clear()
{
if (_aumid != null)
{
_history.Clear(_aumid);
}
else
{
_history.Clear();
}
}

/// <summary>
/// Removes an individual toast, with the specified tag label, from action center.
/// </summary>
/// <param name="tag">The tag label of the toast notification to be removed.</param>
public void Remove(string tag)
{
if (_aumid != null)
{
_history.Remove(tag, string.Empty, _aumid);
}
else
{
_history.Remove(tag);
}
}

/// <summary>
/// Removes a toast notification from the action using the notification's tag and group labels.
/// </summary>
/// <param name="tag">The tag label of the toast notification to be removed.</param>
/// <param name="group">The group label of the toast notification to be removed.</param>
public void Remove(string tag, string group)
{
if (_aumid != null)
{
_history.Remove(tag, group, _aumid);
}
else
{
_history.Remove(tag, group);
}
}

/// <summary>
/// Removes a group of toast notifications, identified by the specified group label, from action center.
/// </summary>
/// <param name="group">The group label of the toast notifications to be removed.</param>
public void RemoveGroup(string group)
{
if (_aumid != null)
{
_history.RemoveGroup(group, _aumid);
}
else
{
_history.RemoveGroup(group);
}
}
}
}
153 changes: 153 additions & 0 deletions DFAssist.Core/Toast/Base/DesktopNotificationManagerCompat.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Windows.UI.Notifications;

namespace DFAssist.Core.Toast.Base
{
public class DesktopNotificationManagerCompat
{
// ReSharper disable InconsistentNaming
public const string TOAST_ACTIVATED_LAUNCH_ARG = "-ToastActivated";
// ReSharper restore InconsistentNaming

private static bool _registeredAumidAndComServer;
private static string _aumid;
private static bool _registeredActivator;

/// <summary>
/// If not running under the Desktop Bridge, you must call this method to register your AUMID with the Compat library and to
/// register your COM CLSID and EXE in LocalServer32 registry. Feel free to call this regardless, and we will no-op if running
/// under Desktop Bridge. Call this upon application startup, before calling any other APIs.
/// </summary>
/// <param name="aumid">An AUMID that uniquely identifies your application.</param>
public static void RegisterAumidAndComServer<T>(string aumid)
where T : NotificationActivator
{
if (string.IsNullOrWhiteSpace(aumid))
{
throw new ArgumentException("You must provide an AUMID.", nameof(aumid));
}

// If running as Desktop Bridge
if (DesktopBridgeHelpers.IsRunningAsUwp())
{
// Clear the AUMID since Desktop Bridge doesn't use it, and then we're done.
// Desktop Bridge apps are registered with platform through their manifest.
// Their LocalServer32 key is also registered through their manifest.
_aumid = null;
_registeredAumidAndComServer = true;
return;
}

_aumid = aumid;

var exePath = Process.GetCurrentProcess().MainModule?.FileName;
RegisterComServer<T>(exePath);

_registeredAumidAndComServer = true;
}

private static void RegisterComServer<T>(string exePath)
where T : NotificationActivator
{
// We register the EXE to start up when the notification is activated
var regString = $"SOFTWARE\\Classes\\CLSID\\{{{typeof(T).GUID}}}\\LocalServer32";
var key = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(regString);

// Include a flag so we know this was a toast activation and should wait for COM to process
// We also wrap EXE path in quotes for extra security
key?.SetValue(null, '"' + exePath + '"' + " " + TOAST_ACTIVATED_LAUNCH_ARG);
}

/// <summary>
/// Registers the activator type as a COM server client so that Windows can launch your activator.
/// </summary>
/// <typeparam name="T">Your implementation of NotificationActivator. Must have GUID and ComVisible attributes on class.</typeparam>
public static void RegisterActivator<T>()
where T : NotificationActivator
{
// Register type
var regService = new RegistrationServices();

regService.RegisterTypeForComClients(
typeof(T),
RegistrationClassContext.LocalServer,
RegistrationConnectionType.MultipleUse);

_registeredActivator = true;
}

/// <summary>
/// Creates a toast notifier. You must have called <see cref="RegisterActivator{T}"/> first (and also <see cref="RegisterAumidAndComServer{T}"/> if you're a classic Win32 app), or this will throw an exception.
/// </summary>
/// <returns></returns>
public static ToastNotifier CreateToastNotifier()
{
EnsureRegistered();

return _aumid != null
? ToastNotificationManager.CreateToastNotifier(_aumid) // non Desktop-Bridge
: ToastNotificationManager.CreateToastNotifier();
}

/// <summary>
/// Gets the <see cref="DesktopNotificationHistoryCompat"/> object. You must have called <see cref="RegisterActivator{T}"/> first (and also <see cref="RegisterAumidAndComServer{T}"/> if you're a classic Win32 app), or this will throw an exception.
/// </summary>
public static DesktopNotificationHistoryCompat History
{
get
{
EnsureRegistered();

return new DesktopNotificationHistoryCompat(_aumid);
}
}

private static void EnsureRegistered()
{
// If not registered AUMID yet
if (!_registeredAumidAndComServer)
{
// Check if Desktop Bridge
if (DesktopBridgeHelpers.IsRunningAsUwp())
{
// Implicitly registered, all good!
_registeredAumidAndComServer = true;
}

else
{
// Otherwise, incorrect usage
throw new Exception("You must call RegisterAumidAndComServer first.");
}
}

// If not registered activator yet
if (!_registeredActivator)
{
// Incorrect usage
throw new Exception("You must call RegisterActivator first.");
}
}

/// <summary>
/// Gets a boolean representing whether http images can be used within toasts. This is true if running under Desktop Bridge.
/// </summary>
// ReSharper disable UnusedMember.Global
public static bool CanUseHttpImages => DesktopBridgeHelpers.IsRunningAsUwp();
// ReSharper restore UnusedMember.Global
}
}
Loading

0 comments on commit 2fd3bf8

Please sign in to comment.