mirror of
https://github.com/greenshot/greenshot
synced 2025-08-14 02:37:03 -07:00
Made notifications work again, activation doesn't work yet due to missing ToastActivatorCLSID on the shortcut.
This commit is contained in:
parent
a29f6faa27
commit
f206046010
11 changed files with 392 additions and 269 deletions
|
@ -552,7 +552,10 @@ namespace Greenshot.Helpers {
|
||||||
notifyIconClassicMessageHandler.ShowErrorMessage(eventArgs.Message, 10000);
|
notifyIconClassicMessageHandler.ShowErrorMessage(eventArgs.Message, 10000);
|
||||||
break;
|
break;
|
||||||
case SurfaceMessageTyp.Info:
|
case SurfaceMessageTyp.Info:
|
||||||
notifyIconClassicMessageHandler.ShowInfoMessage(eventArgs.Message, 10000);
|
notifyIconClassicMessageHandler.ShowInfoMessage(eventArgs.Message, 10000, () =>
|
||||||
|
{
|
||||||
|
Log.Info("Clicked!");
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
case SurfaceMessageTyp.FileSaved:
|
case SurfaceMessageTyp.FileSaved:
|
||||||
case SurfaceMessageTyp.UploadedUri:
|
case SurfaceMessageTyp.UploadedUri:
|
||||||
|
|
|
@ -189,10 +189,11 @@ Root: HKLM; Subkey: Software\Classes\Greenshot\DefaultIcon; ValueType: string; V
|
||||||
Root: HKLM; Subkey: Software\Classes\Greenshot\shell\open\command; ValueType: string; ValueName: ""; ValueData: """{app}\Greenshot.EXE"" --openfile ""%1"""; Permissions: admins-modify; Flags: uninsdeletevalue noerror; Check: not IsRegularUser
|
Root: HKLM; Subkey: Software\Classes\Greenshot\shell\open\command; ValueType: string; ValueName: ""; ValueData: """{app}\Greenshot.EXE"" --openfile ""%1"""; Permissions: admins-modify; Flags: uninsdeletevalue noerror; Check: not IsRegularUser
|
||||||
|
|
||||||
[Icons]
|
[Icons]
|
||||||
Name: {group}\{#ExeName}; Filename: {app}\{#ExeName}.exe; WorkingDir: {app}
|
Name: {group}\{#ExeName}; Filename: {app}\{#ExeName}.exe; WorkingDir: {app}; AppUserModelID: "{#ExeName}"
|
||||||
Name: {group}\Uninstall {#ExeName}; Filename: {uninstallexe}; WorkingDir: {app}; AppUserModelID: "{#ExeName}.{#ExeName}"
|
Name: {group}\Uninstall {#ExeName}; Filename: {uninstallexe}; WorkingDir: {app};
|
||||||
Name: {group}\Readme.txt; Filename: {app}\readme.txt; WorkingDir: {app}
|
Name: {group}\Readme.txt; Filename: {app}\readme.txt; WorkingDir: {app}
|
||||||
Name: {group}\License.txt; Filename: {app}\license.txt; WorkingDir: {app}
|
Name: {group}\License.txt; Filename: {app}\license.txt; WorkingDir: {app}
|
||||||
|
|
||||||
[Languages]
|
[Languages]
|
||||||
Name: en; MessagesFile: compiler:Default.isl
|
Name: en; MessagesFile: compiler:Default.isl
|
||||||
Name: cn; MessagesFile: Languages\ChineseSimplified.isl
|
Name: cn; MessagesFile: Languages\ChineseSimplified.isl
|
||||||
|
|
53
GreenshotWin10Plugin/Native/DesktopBridgeHelpers.cs
Normal file
53
GreenshotWin10Plugin/Native/DesktopBridgeHelpers.cs
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
// ******************************************************************
|
||||||
|
// 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.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using GreenshotPlugin.Core;
|
||||||
|
|
||||||
|
namespace GreenshotWin10Plugin.Native
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Code from https://github.com/qmatteoq/DesktopBridgeHelpers/edit/master/DesktopBridge.Helpers/Helpers.cs
|
||||||
|
/// </summary>
|
||||||
|
public static class DesktopBridgeHelpers
|
||||||
|
{
|
||||||
|
const long AppModelErrorNoPackage = 15700L;
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||||
|
static extern int GetCurrentPackageFullName(ref int packageFullNameLength, StringBuilder packageFullName);
|
||||||
|
|
||||||
|
private static bool? _isRunningAsUwp;
|
||||||
|
public static bool IsRunningAsUwp()
|
||||||
|
{
|
||||||
|
if (_isRunningAsUwp != null) return _isRunningAsUwp.Value;
|
||||||
|
|
||||||
|
if (WindowsVersion.IsWindows7OrLower)
|
||||||
|
{
|
||||||
|
_isRunningAsUwp = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int length = 0;
|
||||||
|
StringBuilder sb = new StringBuilder(0);
|
||||||
|
GetCurrentPackageFullName(ref length, sb);
|
||||||
|
|
||||||
|
sb = new StringBuilder(length);
|
||||||
|
int result = GetCurrentPackageFullName(ref length, sb);
|
||||||
|
|
||||||
|
_isRunningAsUwp = result != AppModelErrorNoPackage;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _isRunningAsUwp.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
109
GreenshotWin10Plugin/Native/DesktopNotificationHistoryCompat.cs
Normal file
109
GreenshotWin10Plugin/Native/DesktopNotificationHistoryCompat.cs
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
// ******************************************************************
|
||||||
|
// 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.Collections.Generic;
|
||||||
|
using Windows.UI.Notifications;
|
||||||
|
|
||||||
|
namespace GreenshotWin10Plugin.Native
|
||||||
|
{
|
||||||
|
/// <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 _applicationUserModelId;
|
||||||
|
private readonly ToastNotificationHistory _history;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Do not call this. Instead, call <see cref="DesktopNotificationManagerCompat.History"/> to obtain an instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="applicationUserModelId"></param>
|
||||||
|
internal DesktopNotificationHistoryCompat(string applicationUserModelId)
|
||||||
|
{
|
||||||
|
_applicationUserModelId = applicationUserModelId;
|
||||||
|
_history = ToastNotificationManager.History;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes all notifications sent by this app from action center.
|
||||||
|
/// </summary>
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
if (_applicationUserModelId != null)
|
||||||
|
{
|
||||||
|
_history.Clear(_applicationUserModelId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_history.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets all notifications sent by this app that are currently still in Action Center.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A collection of toasts.</returns>
|
||||||
|
public IReadOnlyList<ToastNotification> GetHistory()
|
||||||
|
{
|
||||||
|
return _applicationUserModelId != null ? _history.GetHistory(_applicationUserModelId) : _history.GetHistory();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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 (_applicationUserModelId != null)
|
||||||
|
{
|
||||||
|
_history.Remove(tag, string.Empty, _applicationUserModelId);
|
||||||
|
}
|
||||||
|
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 (_applicationUserModelId != null)
|
||||||
|
{
|
||||||
|
_history.Remove(tag, group, _applicationUserModelId);
|
||||||
|
}
|
||||||
|
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 (_applicationUserModelId != null)
|
||||||
|
{
|
||||||
|
_history.RemoveGroup(group, _applicationUserModelId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_history.RemoveGroup(group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,37 +11,31 @@
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
|
||||||
using Windows.UI.Notifications;
|
using Windows.UI.Notifications;
|
||||||
using GreenshotPlugin.Core;
|
|
||||||
|
|
||||||
namespace GreenshotWin10Plugin.Native
|
namespace GreenshotWin10Plugin.Native
|
||||||
{
|
{
|
||||||
public class DesktopNotificationManagerCompat
|
public static class DesktopNotificationManagerCompat
|
||||||
{
|
{
|
||||||
public const string TOAST_ACTIVATED_LAUNCH_ARG = "-ToastActivated";
|
public const string TOAST_ACTIVATED_LAUNCH_ARG = "-ToastActivated";
|
||||||
|
|
||||||
private static bool _registeredAumidAndComServer;
|
private static bool _registeredAumidAndComServer;
|
||||||
private static string _aumid;
|
private static string _applicationUserModelId;
|
||||||
private static bool _registeredActivator;
|
private static bool _registeredActivator;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If not running under the Desktop Bridge, you must call this method to register your AUMID with the Compat library and to
|
/// If not running under the Desktop Bridge, you must call this method to register your applicationUserModelId (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
|
/// 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.
|
/// under Desktop Bridge. Call this upon application startup, before calling any other APIs.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="aumid">An AUMID that uniquely identifies your application.</param>
|
/// <param name="applicationUserModelId">An applicationUserModelId (AUMID) that uniquely identifies your application.</param>
|
||||||
public static void RegisterAumidAndComServer<T>(string aumid)
|
public static void RegisterAumidAndComServer<T>(string applicationUserModelId) where T : NotificationActivator
|
||||||
where T : NotificationActivator
|
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(aumid))
|
if (string.IsNullOrWhiteSpace(applicationUserModelId))
|
||||||
{
|
{
|
||||||
throw new ArgumentException("You must provide an AUMID.", nameof(aumid));
|
throw new ArgumentException("You must provide an Application User Model Id (AUMID).", nameof(applicationUserModelId));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If running as Desktop Bridge
|
// If running as Desktop Bridge
|
||||||
|
@ -50,29 +44,41 @@ namespace GreenshotWin10Plugin.Native
|
||||||
// Clear the AUMID since Desktop Bridge doesn't use it, and then we're done.
|
// 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.
|
// Desktop Bridge apps are registered with platform through their manifest.
|
||||||
// Their LocalServer32 key is also registered through their manifest.
|
// Their LocalServer32 key is also registered through their manifest.
|
||||||
_aumid = null;
|
_applicationUserModelId = null;
|
||||||
_registeredAumidAndComServer = true;
|
_registeredAumidAndComServer = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_aumid = aumid;
|
_applicationUserModelId = applicationUserModelId;
|
||||||
|
|
||||||
String exePath = Process.GetCurrentProcess().MainModule.FileName;
|
string exePath = Process.GetCurrentProcess().MainModule?.FileName;
|
||||||
RegisterComServer<T>(exePath);
|
if (exePath != null)
|
||||||
|
{
|
||||||
|
RegisterComServer<T>(exePath);
|
||||||
|
}
|
||||||
|
|
||||||
_registeredAumidAndComServer = true;
|
_registeredAumidAndComServer = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void RegisterComServer<T>(string exePath)
|
/// <summary>
|
||||||
where T : NotificationActivator
|
/// Register the application an a com server
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">type to register for</typeparam>
|
||||||
|
/// <param name="exePath">string</param>
|
||||||
|
private static void RegisterComServer<T>(string exePath) where T : NotificationActivator
|
||||||
{
|
{
|
||||||
// We register the EXE to start up when the notification is activated
|
// We register the EXE to start up when the notification is activated
|
||||||
string regString = $"SOFTWARE\\Classes\\CLSID\\{{{typeof(T).GUID}}}\\LocalServer32";
|
var guid = typeof(T).GUID;
|
||||||
var key = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(regString);
|
if (guid == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("You must provide an Guid on your NotificationActivator.");
|
||||||
|
}
|
||||||
|
string regString = $"SOFTWARE\\Classes\\CLSID\\{{{guid}}}\\LocalServer32";
|
||||||
|
using 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
|
// 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
|
// We also wrap EXE path in quotes for extra security
|
||||||
key.SetValue(null, '"' + exePath + '"' + " " + TOAST_ACTIVATED_LAUNCH_ARG);
|
key?.SetValue(null, '"' + exePath + '"' + " " + TOAST_ACTIVATED_LAUNCH_ARG);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -84,26 +90,23 @@ namespace GreenshotWin10Plugin.Native
|
||||||
// Register type
|
// Register type
|
||||||
var regService = new RegistrationServices();
|
var regService = new RegistrationServices();
|
||||||
|
|
||||||
regService.RegisterTypeForComClients(
|
regService.RegisterTypeForComClients(typeof(T), RegistrationClassContext.LocalServer, RegistrationConnectionType.MultipleUse);
|
||||||
typeof(T),
|
|
||||||
RegistrationClassContext.LocalServer,
|
|
||||||
RegistrationConnectionType.MultipleUse);
|
|
||||||
|
|
||||||
_registeredActivator = true;
|
_registeredActivator = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a toast notifier. You must have called <see cref="RegisterActivator{T}"/> first (and also <see cref="RegisterAumidAndComServer(string)"/> if you're a classic Win32 app), or this will throw an exception.
|
/// 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>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns>ToastNotifier</returns>
|
||||||
public static ToastNotifier CreateToastNotifier()
|
public static ToastNotifier CreateToastNotifier()
|
||||||
{
|
{
|
||||||
EnsureRegistered();
|
EnsureRegistered();
|
||||||
|
|
||||||
if (_aumid != null)
|
if (_applicationUserModelId != null)
|
||||||
{
|
{
|
||||||
// Non-Desktop Bridge
|
// Non-Desktop Bridge
|
||||||
return ToastNotificationManager.CreateToastNotifier(_aumid);
|
return ToastNotificationManager.CreateToastNotifier(_applicationUserModelId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Desktop Bridge
|
// Desktop Bridge
|
||||||
|
@ -111,7 +114,7 @@ namespace GreenshotWin10Plugin.Native
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the <see cref="DesktopNotificationHistoryCompat"/> object. You must have called <see cref="RegisterActivator{T}"/> first (and also <see cref="RegisterAumidAndComServer(string)"/> if you're a classic Win32 app), or this will throw an exception.
|
/// 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>
|
/// </summary>
|
||||||
public static DesktopNotificationHistoryCompat History
|
public static DesktopNotificationHistoryCompat History
|
||||||
{
|
{
|
||||||
|
@ -119,10 +122,13 @@ namespace GreenshotWin10Plugin.Native
|
||||||
{
|
{
|
||||||
EnsureRegistered();
|
EnsureRegistered();
|
||||||
|
|
||||||
return new DesktopNotificationHistoryCompat(_aumid);
|
return new DesktopNotificationHistoryCompat(_applicationUserModelId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the AUMID is correctly registered, if not this throws an exception
|
||||||
|
/// </summary>
|
||||||
private static void EnsureRegistered()
|
private static void EnsureRegistered()
|
||||||
{
|
{
|
||||||
// If not registered AUMID yet
|
// If not registered AUMID yet
|
||||||
|
@ -153,232 +159,6 @@ namespace GreenshotWin10Plugin.Native
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a boolean representing whether http images can be used within toasts. This is true if running under Desktop Bridge.
|
/// Gets a boolean representing whether http images can be used within toasts. This is true if running under Desktop Bridge.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool CanUseHttpImages { get { return DesktopBridgeHelpers.IsRunningAsUwp(); } }
|
public static bool CanUseHttpImages => DesktopBridgeHelpers.IsRunningAsUwp();
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Code from https://github.com/qmatteoq/DesktopBridgeHelpers/edit/master/DesktopBridge.Helpers/Helpers.cs
|
|
||||||
/// </summary>
|
|
||||||
private static class DesktopBridgeHelpers
|
|
||||||
{
|
|
||||||
const long APPMODEL_ERROR_NO_PACKAGE = 15700L;
|
|
||||||
|
|
||||||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
|
||||||
static extern int GetCurrentPackageFullName(ref int packageFullNameLength, StringBuilder packageFullName);
|
|
||||||
|
|
||||||
private static bool? _isRunningAsUwp;
|
|
||||||
public static bool IsRunningAsUwp()
|
|
||||||
{
|
|
||||||
if (_isRunningAsUwp != null) return _isRunningAsUwp.Value;
|
|
||||||
|
|
||||||
if (WindowsVersion.IsWindows7OrLower)
|
|
||||||
{
|
|
||||||
_isRunningAsUwp = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int length = 0;
|
|
||||||
StringBuilder sb = new StringBuilder(0);
|
|
||||||
GetCurrentPackageFullName(ref length, sb);
|
|
||||||
|
|
||||||
sb = new StringBuilder(length);
|
|
||||||
int result = GetCurrentPackageFullName(ref length, sb);
|
|
||||||
|
|
||||||
_isRunningAsUwp = result != APPMODEL_ERROR_NO_PACKAGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _isRunningAsUwp.Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <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 string _aumid;
|
|
||||||
private ToastNotificationHistory _history;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Do not call this. Instead, call <see cref="DesktopNotificationManagerCompat.History"/> to obtain an instance.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="aumid"></param>
|
|
||||||
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>
|
|
||||||
/// Gets all notifications sent by this app that are currently still in Action Center.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>A collection of toasts.</returns>
|
|
||||||
public IReadOnlyList<ToastNotification> GetHistory()
|
|
||||||
{
|
|
||||||
return _aumid != null ? _history.GetHistory(_aumid) : _history.GetHistory();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Apps must implement this activator to handle notification activation.
|
|
||||||
/// </summary>
|
|
||||||
public abstract class NotificationActivator : NotificationActivator.INotificationActivationCallback
|
|
||||||
{
|
|
||||||
public void Activate(string appUserModelId, string invokedArgs, NOTIFICATION_USER_INPUT_DATA[] data, uint dataCount)
|
|
||||||
{
|
|
||||||
OnActivated(invokedArgs, new NotificationUserInput(data), appUserModelId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This method will be called when the user clicks on a foreground or background activation on a toast. Parent app must implement this method.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="arguments">The arguments from the original notification. This is either the launch argument if the user clicked the body of your toast, or the arguments from a button on your toast.</param>
|
|
||||||
/// <param name="userInput">Text and selection values that the user entered in your toast.</param>
|
|
||||||
/// <param name="appUserModelId">Your AUMID.</param>
|
|
||||||
public abstract void OnActivated(string arguments, NotificationUserInput userInput, string appUserModelId);
|
|
||||||
|
|
||||||
// These are the new APIs for Windows 10
|
|
||||||
#region NewAPIs
|
|
||||||
[StructLayout(LayoutKind.Sequential), Serializable]
|
|
||||||
public struct NOTIFICATION_USER_INPUT_DATA
|
|
||||||
{
|
|
||||||
[MarshalAs(UnmanagedType.LPWStr)]
|
|
||||||
public string Key;
|
|
||||||
|
|
||||||
[MarshalAs(UnmanagedType.LPWStr)]
|
|
||||||
public string Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
[ComImport,
|
|
||||||
Guid("53E31837-6600-4A81-9395-75CFFE746F94"), ComVisible(true),
|
|
||||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
||||||
public interface INotificationActivationCallback
|
|
||||||
{
|
|
||||||
void Activate(
|
|
||||||
[In, MarshalAs(UnmanagedType.LPWStr)]
|
|
||||||
string appUserModelId,
|
|
||||||
[In, MarshalAs(UnmanagedType.LPWStr)]
|
|
||||||
string invokedArgs,
|
|
||||||
[In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)]
|
|
||||||
NOTIFICATION_USER_INPUT_DATA[] data,
|
|
||||||
[In, MarshalAs(UnmanagedType.U4)]
|
|
||||||
uint dataCount);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Text and selection values that the user entered on your notification. The Key is the ID of the input, and the Value is what the user entered.
|
|
||||||
/// </summary>
|
|
||||||
public class NotificationUserInput : IReadOnlyDictionary<string, string>
|
|
||||||
{
|
|
||||||
private NotificationActivator.NOTIFICATION_USER_INPUT_DATA[] _data;
|
|
||||||
|
|
||||||
internal NotificationUserInput(NotificationActivator.NOTIFICATION_USER_INPUT_DATA[] data)
|
|
||||||
{
|
|
||||||
_data = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string this[string key] => _data.First(i => i.Key == key).Value;
|
|
||||||
|
|
||||||
public IEnumerable<string> Keys => _data.Select(i => i.Key);
|
|
||||||
|
|
||||||
public IEnumerable<string> Values => _data.Select(i => i.Value);
|
|
||||||
|
|
||||||
public int Count => _data.Length;
|
|
||||||
|
|
||||||
public bool ContainsKey(string key)
|
|
||||||
{
|
|
||||||
return _data.Any(i => i.Key == key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
|
|
||||||
{
|
|
||||||
return _data.Select(i => new KeyValuePair<string, string>(i.Key, i.Value)).GetEnumerator();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool TryGetValue(string key, out string value)
|
|
||||||
{
|
|
||||||
foreach (var item in _data)
|
|
||||||
{
|
|
||||||
if (item.Key == key)
|
|
||||||
{
|
|
||||||
value = item.Value;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
value = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
|
||||||
{
|
|
||||||
return GetEnumerator();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -24,7 +24,9 @@ using log4net;
|
||||||
|
|
||||||
namespace GreenshotWin10Plugin.Native
|
namespace GreenshotWin10Plugin.Native
|
||||||
{
|
{
|
||||||
// The GUID CLSID must be unique to your app. Create a new GUID if copying this code.
|
/// <summary>
|
||||||
|
/// This implements the NotificationActivator
|
||||||
|
/// </summary>
|
||||||
[ClassInterface(ClassInterfaceType.None)]
|
[ClassInterface(ClassInterfaceType.None)]
|
||||||
[ComSourceInterfaces(typeof(INotificationActivationCallback))]
|
[ComSourceInterfaces(typeof(INotificationActivationCallback))]
|
||||||
[Guid("F48E86D3-E34C-4DB7-8F8F-9A0EA55F0D08"), ComVisible(true)]
|
[Guid("F48E86D3-E34C-4DB7-8F8F-9A0EA55F0D08"), ComVisible(true)]
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
// ******************************************************************
|
||||||
|
// 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.Runtime.InteropServices;
|
||||||
|
using GreenshotWin10Plugin.Native.Structs;
|
||||||
|
|
||||||
|
namespace GreenshotWin10Plugin.Native
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This is the interface which allows your notifications to be clicked, which active the application
|
||||||
|
/// </summary>
|
||||||
|
[ComImport, Guid("53E31837-6600-4A81-9395-75CFFE746F94"),
|
||||||
|
ComVisible(true), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||||
|
public interface INotificationActivationCallback
|
||||||
|
{
|
||||||
|
void Activate(
|
||||||
|
[In, MarshalAs(UnmanagedType.LPWStr)]
|
||||||
|
string appUserModelId,
|
||||||
|
[In, MarshalAs(UnmanagedType.LPWStr)]
|
||||||
|
string invokedArgs,
|
||||||
|
[In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)]
|
||||||
|
NotificationUserInputData[] data,
|
||||||
|
[In, MarshalAs(UnmanagedType.U4)]
|
||||||
|
uint dataCount);
|
||||||
|
}
|
||||||
|
}
|
35
GreenshotWin10Plugin/Native/NotificationActivator.cs
Normal file
35
GreenshotWin10Plugin/Native/NotificationActivator.cs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
// ******************************************************************
|
||||||
|
// 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 GreenshotWin10Plugin.Native.Structs;
|
||||||
|
|
||||||
|
namespace GreenshotWin10Plugin.Native
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Apps must implement this activator to handle notification activation.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class NotificationActivator : INotificationActivationCallback
|
||||||
|
{
|
||||||
|
public void Activate(string appUserModelId, string invokedArgs, NotificationUserInputData[] data, uint dataCount)
|
||||||
|
{
|
||||||
|
OnActivated(invokedArgs, new NotificationUserInput(data), appUserModelId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This method will be called when the user clicks on a foreground or background activation on a toast. Parent app must implement this method.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="arguments">The arguments from the original notification. This is either the launch argument if the user clicked the body of your toast, or the arguments from a button on your toast.</param>
|
||||||
|
/// <param name="userInput">Text and selection values that the user entered in your toast.</param>
|
||||||
|
/// <param name="appUserModelId">Your AUMID.</param>
|
||||||
|
public abstract void OnActivated(string arguments, NotificationUserInput userInput, string appUserModelId);
|
||||||
|
}
|
||||||
|
}
|
70
GreenshotWin10Plugin/Native/NotificationUserInput.cs
Normal file
70
GreenshotWin10Plugin/Native/NotificationUserInput.cs
Normal file
|
@ -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.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using GreenshotWin10Plugin.Native.Structs;
|
||||||
|
|
||||||
|
namespace GreenshotWin10Plugin.Native
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Text and selection values that the user entered on your notification. The Key is the ID of the input, and the Value is what the user entered.
|
||||||
|
/// </summary>
|
||||||
|
public class NotificationUserInput : IReadOnlyDictionary<string, string>
|
||||||
|
{
|
||||||
|
private readonly NotificationUserInputData[] _notificationUserInputData;
|
||||||
|
|
||||||
|
internal NotificationUserInput(NotificationUserInputData[] notificationUserInputData)
|
||||||
|
{
|
||||||
|
_notificationUserInputData = notificationUserInputData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string this[string key] => _notificationUserInputData.First(i => i.Key == key).Value;
|
||||||
|
|
||||||
|
public IEnumerable<string> Keys => _notificationUserInputData.Select(i => i.Key);
|
||||||
|
|
||||||
|
public IEnumerable<string> Values => _notificationUserInputData.Select(i => i.Value);
|
||||||
|
|
||||||
|
public int Count => _notificationUserInputData.Length;
|
||||||
|
|
||||||
|
public bool ContainsKey(string key)
|
||||||
|
{
|
||||||
|
return _notificationUserInputData.Any(i => i.Key == key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
|
||||||
|
{
|
||||||
|
return _notificationUserInputData.Select(i => new KeyValuePair<string, string>(i.Key, i.Value)).GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetValue(string key, out string value)
|
||||||
|
{
|
||||||
|
foreach (var item in _notificationUserInputData)
|
||||||
|
{
|
||||||
|
if (item.Key == key)
|
||||||
|
{
|
||||||
|
value = item.Value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
value = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
return GetEnumerator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
// ******************************************************************
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
namespace GreenshotWin10Plugin.Native.Structs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// See <a href="https://docs.microsoft.com/en-us/windows/win32/api/notificationactivationcallback/ns-notificationactivationcallback-notification_user_input_data">NOTIFICATION_USER_INPUT_DATA structure</a>
|
||||||
|
/// </summary>
|
||||||
|
[StructLayout(LayoutKind.Sequential), Serializable]
|
||||||
|
public struct NotificationUserInputData
|
||||||
|
{
|
||||||
|
[MarshalAs(UnmanagedType.LPWStr)]
|
||||||
|
public string Key;
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.LPWStr)]
|
||||||
|
public string Value;
|
||||||
|
}
|
||||||
|
}
|
|
@ -44,7 +44,7 @@ namespace GreenshotWin10Plugin
|
||||||
public ToastNotificationService()
|
public ToastNotificationService()
|
||||||
{
|
{
|
||||||
// Register AUMID and COM server (for Desktop Bridge apps, this no-ops)
|
// Register AUMID and COM server (for Desktop Bridge apps, this no-ops)
|
||||||
DesktopNotificationManagerCompat.RegisterAumidAndComServer<GreenshotNotificationActivator>("Greenshot.Greenshot");
|
DesktopNotificationManagerCompat.RegisterAumidAndComServer<GreenshotNotificationActivator>("Greenshot");
|
||||||
// Register COM server and activator type
|
// Register COM server and activator type
|
||||||
DesktopNotificationManagerCompat.RegisterActivator<GreenshotNotificationActivator>();
|
DesktopNotificationManagerCompat.RegisterActivator<GreenshotNotificationActivator>();
|
||||||
|
|
||||||
|
@ -68,9 +68,10 @@ namespace GreenshotWin10Plugin
|
||||||
/// This creates the actual toast
|
/// This creates the actual toast
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="message">string</param>
|
/// <param name="message">string</param>
|
||||||
|
/// <param name="timeout">milliseconds until the toast timeouts</param>
|
||||||
/// <param name="onClickAction">Action called when clicked</param>
|
/// <param name="onClickAction">Action called when clicked</param>
|
||||||
/// <param name="onClosedAction">Action called when the toast is closed</param>
|
/// <param name="onClosedAction">Action called when the toast is closed</param>
|
||||||
private void ShowMessage(string message, Action onClickAction, Action onClosedAction)
|
private void ShowMessage(string message, int timeout, Action onClickAction, Action onClosedAction)
|
||||||
{
|
{
|
||||||
// Do not inform the user if this is disabled
|
// Do not inform the user if this is disabled
|
||||||
if (!CoreConfiguration.ShowTrayNotification)
|
if (!CoreConfiguration.ShowTrayNotification)
|
||||||
|
@ -104,7 +105,11 @@ namespace GreenshotWin10Plugin
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the toast and attach event listeners
|
// Create the toast and attach event listeners
|
||||||
var toast = new ToastNotification(toastXml);
|
var toast = new ToastNotification(toastXml)
|
||||||
|
{
|
||||||
|
ExpiresOnReboot = true,
|
||||||
|
ExpirationTime = timeout > 0 ? DateTimeOffset.Now.AddMilliseconds(timeout) : (DateTimeOffset?)null
|
||||||
|
};
|
||||||
|
|
||||||
void ToastActivatedHandler(ToastNotification toastNotification, object sender)
|
void ToastActivatedHandler(ToastNotification toastNotification, object sender)
|
||||||
{
|
{
|
||||||
|
@ -155,17 +160,17 @@ namespace GreenshotWin10Plugin
|
||||||
|
|
||||||
public void ShowWarningMessage(string message, int timeout, Action onClickAction = null, Action onClosedAction = null)
|
public void ShowWarningMessage(string message, int timeout, Action onClickAction = null, Action onClosedAction = null)
|
||||||
{
|
{
|
||||||
ShowMessage(message, onClickAction, onClosedAction);
|
ShowMessage(message, timeout, onClickAction, onClosedAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ShowErrorMessage(string message, int timeout, Action onClickAction = null, Action onClosedAction = null)
|
public void ShowErrorMessage(string message, int timeout, Action onClickAction = null, Action onClosedAction = null)
|
||||||
{
|
{
|
||||||
ShowMessage(message, onClickAction, onClosedAction);
|
ShowMessage(message, timeout, onClickAction, onClosedAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ShowInfoMessage(string message, int timeout, Action onClickAction = null, Action onClosedAction = null)
|
public void ShowInfoMessage(string message, int timeout, Action onClickAction = null, Action onClosedAction = null)
|
||||||
{
|
{
|
||||||
ShowMessage(message, onClickAction, onClosedAction);
|
ShowMessage(message, timeout, onClickAction, onClosedAction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue