mirror of
https://github.com/ONLYOFFICE/desktop-apps.git
synced 2026-04-07 14:09:22 +08:00
[win-linux] updmanager: add system update notification
This commit is contained in:
@ -155,8 +155,10 @@ SOURCES += \
|
|||||||
$$PWD/src/cthemes.cpp
|
$$PWD/src/cthemes.cpp
|
||||||
|
|
||||||
updmodule:!build_xp {
|
updmodule:!build_xp {
|
||||||
HEADERS += $$PWD/src/cupdatemanager.h
|
HEADERS += $$PWD/src/cupdatemanager.h \
|
||||||
SOURCES += $$PWD/src/cupdatemanager.cpp
|
$$PWD/src/components/cnotification.h
|
||||||
|
SOURCES += $$PWD/src/cupdatemanager.cpp \
|
||||||
|
$$PWD/src/components/cnotification.cpp
|
||||||
}
|
}
|
||||||
|
|
||||||
RESOURCES += $$PWD/resources.qrc
|
RESOURCES += $$PWD/resources.qrc
|
||||||
@ -228,8 +230,10 @@ core_linux {
|
|||||||
$$PWD/extras/update-daemon/src/classes/csocket.cpp
|
$$PWD/extras/update-daemon/src/classes/csocket.cpp
|
||||||
|
|
||||||
updmodule {
|
updmodule {
|
||||||
|
QT += dbus
|
||||||
HEADERS += $$PWD/src/platform_linux/updatedialog.h
|
HEADERS += $$PWD/src/platform_linux/updatedialog.h
|
||||||
SOURCES += $$PWD/src/platform_linux/updatedialog.cpp
|
SOURCES += $$PWD/src/platform_linux/updatedialog.cpp
|
||||||
|
PKGCONFIG += libnotify
|
||||||
}
|
}
|
||||||
|
|
||||||
CONFIG += link_pkgconfig
|
CONFIG += link_pkgconfig
|
||||||
@ -277,8 +281,10 @@ core_windows {
|
|||||||
updmodule:!build_xp {
|
updmodule:!build_xp {
|
||||||
INCLUDEPATH += $$PWD/extras/update-daemon/src/classes
|
INCLUDEPATH += $$PWD/extras/update-daemon/src/classes
|
||||||
HEADERS += $$PWD/src/platform_win/updatedialog.h \
|
HEADERS += $$PWD/src/platform_win/updatedialog.h \
|
||||||
|
$$PWD/src/platform_win/wintoastlib.h \
|
||||||
$$PWD/extras/update-daemon/src/classes/csocket.h
|
$$PWD/extras/update-daemon/src/classes/csocket.h
|
||||||
SOURCES += $$PWD/src/platform_win/updatedialog.cpp \
|
SOURCES += $$PWD/src/platform_win/updatedialog.cpp \
|
||||||
|
$$PWD/src/platform_win/wintoastlib.cpp \
|
||||||
$$PWD/extras/update-daemon/src/classes/csocket.cpp
|
$$PWD/extras/update-daemon/src/classes/csocket.cpp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -330,6 +330,7 @@ bool CAscApplicationManagerWrapper::processCommonEvent(NSEditorApi::CAscCefMenuE
|
|||||||
#ifdef _UPDMODULE
|
#ifdef _UPDMODULE
|
||||||
if ( !(cmd.find(L"updates:action") == std::wstring::npos) ) { // params: check, download, install, abort
|
if ( !(cmd.find(L"updates:action") == std::wstring::npos) ) { // params: check, download, install, abort
|
||||||
if (m_pUpdateManager) {
|
if (m_pUpdateManager) {
|
||||||
|
CNotification::instance().clear();
|
||||||
const QString params = QString::fromStdWString(pData->get_Param());
|
const QString params = QString::fromStdWString(pData->get_Param());
|
||||||
if (params == "check") {
|
if (params == "check") {
|
||||||
m_pUpdateManager->checkUpdates(true);
|
m_pUpdateManager->checkUpdates(true);
|
||||||
|
|||||||
@ -42,6 +42,7 @@
|
|||||||
#include "ccefeventstransformer.h"
|
#include "ccefeventstransformer.h"
|
||||||
#include "ccefeventsgate.h"
|
#include "ccefeventsgate.h"
|
||||||
#include "windows/ceditorwindow.h"
|
#include "windows/ceditorwindow.h"
|
||||||
|
#include "components/cnotification.h"
|
||||||
#include "cwindowsqueue.h"
|
#include "cwindowsqueue.h"
|
||||||
#include "ceventdriver.h"
|
#include "ceventdriver.h"
|
||||||
#include "cprintdata.h"
|
#include "cprintdata.h"
|
||||||
|
|||||||
361
win-linux/src/components/cnotification.cpp
Normal file
361
win-linux/src/components/cnotification.cpp
Normal file
@ -0,0 +1,361 @@
|
|||||||
|
/*
|
||||||
|
* (c) Copyright Ascensio System SIA 2010-2019
|
||||||
|
*
|
||||||
|
* This program is a free software product. You can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
||||||
|
* version 3 as published by the Free Software Foundation. In accordance with
|
||||||
|
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
|
||||||
|
* that Ascensio System SIA expressly excludes the warranty of non-infringement
|
||||||
|
* of any third-party rights.
|
||||||
|
*
|
||||||
|
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
||||||
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
||||||
|
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||||
|
*
|
||||||
|
* You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
|
||||||
|
* street, Riga, Latvia, EU, LV-1050.
|
||||||
|
*
|
||||||
|
* The interactive user interfaces in modified source and object code versions
|
||||||
|
* of the Program must display Appropriate Legal Notices, as required under
|
||||||
|
* Section 5 of the GNU AGPL version 3.
|
||||||
|
*
|
||||||
|
* Pursuant to Section 7(b) of the License you must retain the original Product
|
||||||
|
* logo when distributing the program. Pursuant to Section 7(e) we decline to
|
||||||
|
* grant you any rights under trademark law for use of our trademarks.
|
||||||
|
*
|
||||||
|
* All the Product's GUI elements, including illustrations and icon sets, as
|
||||||
|
* well as technical writing content are licensed under the terms of the
|
||||||
|
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
|
||||||
|
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# include <QCoreApplication>
|
||||||
|
# include "utils.h"
|
||||||
|
#else
|
||||||
|
# include <libnotify/notify.h>
|
||||||
|
# include <gio/gio.h>
|
||||||
|
# include <glib.h>
|
||||||
|
# include <unordered_map>
|
||||||
|
# include "utils.h"
|
||||||
|
# include <QDBusConnection>
|
||||||
|
# include <QDBusInterface>
|
||||||
|
# include <QDBusMessage>
|
||||||
|
# include <QDBusVariant>
|
||||||
|
#endif
|
||||||
|
#include <QTextDocumentFragment>
|
||||||
|
#include "components/cnotification.h"
|
||||||
|
#include "defines.h"
|
||||||
|
|
||||||
|
#define NOTIF_TIMEOUT_MS 10000
|
||||||
|
#ifdef __linux__
|
||||||
|
# define toTStr(qstr) qstr.toStdString()
|
||||||
|
#else
|
||||||
|
# define toTStr(qstr) qstr.toStdWString()
|
||||||
|
#endif
|
||||||
|
#define TEXT_SKIP toTStr(QObject::tr("Skip"))
|
||||||
|
#define TEXT_REMIND toTStr(QObject::tr("Later"))
|
||||||
|
#define TEXT_INSTALL toTStr(QObject::tr("Install"))
|
||||||
|
#define TEXT_INSLATER toTStr(QObject::tr("Later"))
|
||||||
|
#define TEXT_RESTART toTStr(QObject::tr("Restart"))
|
||||||
|
#define TEXT_SAVEANDINS toTStr(QObject::tr("Install"))
|
||||||
|
#define TEXT_DOWNLOAD toTStr(QObject::tr("Download"))
|
||||||
|
|
||||||
|
using namespace WinDlg;
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
# define addAction(action, label) notify_notification_add_action(ntf, action, label, NOTIFY_ACTION_CALLBACK(action_callback), (void*)&pimpl->ntfMap, NULL);
|
||||||
|
|
||||||
|
typedef std::unordered_map<NotifyNotification*, FnVoidInt> NtfMap;
|
||||||
|
|
||||||
|
static void action_callback(NotifyNotification *ntf, char *action, void *data)
|
||||||
|
{
|
||||||
|
if (!data)
|
||||||
|
return;
|
||||||
|
int res = strcmp(action, "inslater") == 0 ? DLG_RESULT_INSLATER :
|
||||||
|
strcmp(action, "restart") == 0 ? DLG_RESULT_RESTART :
|
||||||
|
strcmp(action, "skip") == 0 ? DLG_RESULT_SKIP :
|
||||||
|
strcmp(action, "remind") == 0 ? DLG_RESULT_REMIND :
|
||||||
|
strcmp(action, "install") == 0 ? DLG_RESULT_INSTALL :
|
||||||
|
strcmp(action, "saveins") == 0 ? DLG_RESULT_INSTALL :
|
||||||
|
strcmp(action, "download") == 0 ? DLG_RESULT_DOWNLOAD : -1;
|
||||||
|
|
||||||
|
NtfMap *ntfMap = (NtfMap*)data;
|
||||||
|
if (ntfMap->find(ntf) != ntfMap->end()) {
|
||||||
|
if (FnVoidInt callback = ntfMap->at(ntf))
|
||||||
|
callback(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_close(NotifyNotification *ntf, void *data)
|
||||||
|
{
|
||||||
|
if (!data)
|
||||||
|
return;
|
||||||
|
NtfMap *ntfMap = (NtfMap*)data;
|
||||||
|
auto it = ntfMap->find(ntf);
|
||||||
|
if (it != ntfMap->end()) {
|
||||||
|
g_object_unref(ntf);
|
||||||
|
ntfMap->erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isNotificationsEnabled()
|
||||||
|
{
|
||||||
|
if (WindowHelper::getEnvInfo() == WindowHelper::GNOME) {
|
||||||
|
GSettings *stn = g_settings_new("org.gnome.desktop.notifications");
|
||||||
|
GVariant *var = g_settings_get_value(stn, "show-banners");
|
||||||
|
gboolean res = false;
|
||||||
|
g_variant_get(var, "b", &res);
|
||||||
|
g_object_unref(var);
|
||||||
|
g_object_unref(stn);
|
||||||
|
return res;
|
||||||
|
} else
|
||||||
|
if (WindowHelper::getEnvInfo() == WindowHelper::CINNAMON) {
|
||||||
|
GSettings *stn = g_settings_new("org.cinnamon.desktop.notifications");
|
||||||
|
GVariant *var = g_settings_get_value(stn, "display-notifications");
|
||||||
|
gboolean res = false;
|
||||||
|
g_variant_get(var, "b", &res);
|
||||||
|
g_object_unref(var);
|
||||||
|
g_object_unref(stn);
|
||||||
|
return res;
|
||||||
|
} else
|
||||||
|
if (WindowHelper::getEnvInfo() == WindowHelper::KDE) {
|
||||||
|
QDBusConnection conn = QDBusConnection::sessionBus();
|
||||||
|
if (conn.isConnected()) {
|
||||||
|
QDBusInterface itf("org.freedesktop.Notifications", "/org/freedesktop/Notifications", "org.freedesktop.DBus.Properties", conn);
|
||||||
|
if (itf.isValid()) {
|
||||||
|
QDBusMessage msg = itf.call("Get", "org.freedesktop.Notifications", "Inhibited");
|
||||||
|
if (msg.type() == QDBusMessage::ReplyMessage && msg.arguments().size() > 0) {
|
||||||
|
QVariant var = msg.arguments().at(0);
|
||||||
|
if (var.canConvert<QDBusVariant>()) {
|
||||||
|
QVariant res = var.value<QDBusVariant>().variant();
|
||||||
|
if (res.type() == QVariant::Bool && !res.toBool())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
if (WindowHelper::getEnvInfo() == WindowHelper::XFCE) {
|
||||||
|
QDBusConnection conn = QDBusConnection::sessionBus();
|
||||||
|
if (conn.isConnected()) {
|
||||||
|
QDBusInterface itf("org.xfce.Xfconf", "/org/xfce/Xfconf", "org.xfce.Xfconf", conn);
|
||||||
|
if (itf.isValid()) {
|
||||||
|
QDBusMessage msg = itf.call("GetProperty", "xfce4-notifyd", "/do-not-disturb");
|
||||||
|
if (msg.type() == QDBusMessage::ErrorMessage)
|
||||||
|
return true; // By default the property is not defined and notifications are enabled
|
||||||
|
if (msg.type() == QDBusMessage::ReplyMessage && msg.arguments().size() > 0) {
|
||||||
|
QVariant var = msg.arguments().at(0);
|
||||||
|
if (var.canConvert<QDBusVariant>()) {
|
||||||
|
QVariant res = var.value<QDBusVariant>().variant();
|
||||||
|
if (res.type() == QVariant::Bool && !res.toBool())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# include "platform_win/wintoastlib.h"
|
||||||
|
|
||||||
|
using namespace WinToastLib;
|
||||||
|
|
||||||
|
class ToastHandler : public IWinToastHandler {
|
||||||
|
public:
|
||||||
|
ToastHandler(DlgBtns _dlgBtns, FnVoidInt _callback) : dlgBtns(_dlgBtns), callback(_callback)
|
||||||
|
{}
|
||||||
|
virtual void toastActivated() const final // The user clicked in this toast
|
||||||
|
{}
|
||||||
|
virtual void toastActivated(int actionIndex) const final // The user clicked on button #actionIndex
|
||||||
|
{
|
||||||
|
int res = -1;
|
||||||
|
switch (actionIndex) {
|
||||||
|
case 0: res = (dlgBtns == DlgBtns::mbInslaterRestart) ? DLG_RESULT_INSLATER : DLG_RESULT_SKIP; break;
|
||||||
|
case 1: res = (dlgBtns == DlgBtns::mbInslaterRestart) ? DLG_RESULT_RESTART : DLG_RESULT_REMIND; break;
|
||||||
|
case 2: res = (dlgBtns == DlgBtns::mbSkipRemindDownload) ? DLG_RESULT_DOWNLOAD : DLG_RESULT_INSTALL; break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (callback)
|
||||||
|
callback(res);
|
||||||
|
}
|
||||||
|
virtual void toastActivated(const char* response) const final
|
||||||
|
{}
|
||||||
|
virtual void toastFailed() const final // Error showing current toast
|
||||||
|
{
|
||||||
|
if (callback)
|
||||||
|
callback(NOTIF_FAILED);
|
||||||
|
}
|
||||||
|
virtual void toastDismissed(WinToastDismissalReason state) const final
|
||||||
|
{
|
||||||
|
switch (state) {
|
||||||
|
case UserCanceled: // The user dismissed this toast
|
||||||
|
break;
|
||||||
|
case ApplicationHidden: // The application hide the toast using ToastNotifier.hide()
|
||||||
|
break;
|
||||||
|
case TimedOut: // The toast has timed out
|
||||||
|
break;
|
||||||
|
default: // Toast not activated
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
DlgBtns dlgBtns;
|
||||||
|
FnVoidInt callback;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class CNotification::CNotificationPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
#ifdef __linux__
|
||||||
|
~CNotificationPrivate()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
for (auto it = ntfMap.begin(); it != ntfMap.end();) {
|
||||||
|
NotifyNotification *ntf = it->first;
|
||||||
|
it = ntfMap.erase(it);
|
||||||
|
notify_notification_close(ntf, NULL);
|
||||||
|
g_object_unref(ntf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NtfMap ntfMap;
|
||||||
|
#endif
|
||||||
|
int isInit = -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
CNotification& CNotification::instance()
|
||||||
|
{
|
||||||
|
static CNotification inst;
|
||||||
|
return inst;
|
||||||
|
}
|
||||||
|
|
||||||
|
CNotification::CNotification() :
|
||||||
|
pimpl(new CNotificationPrivate)
|
||||||
|
{}
|
||||||
|
|
||||||
|
CNotification::~CNotification()
|
||||||
|
{
|
||||||
|
delete pimpl, pimpl = nullptr;
|
||||||
|
#ifdef __linux__
|
||||||
|
if (notify_is_initted())
|
||||||
|
notify_uninit();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CNotification::init()
|
||||||
|
{
|
||||||
|
if (pimpl->isInit != -1)
|
||||||
|
return pimpl->isInit;
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
pimpl->isInit = notify_init(WINDOW_TITLE);
|
||||||
|
#else
|
||||||
|
if (Utils::getWinVersion() < Utils::WinVer::Win10) {
|
||||||
|
pimpl->isInit = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
WinToast::instance()->setAppName(TEXT(WINDOW_TITLE));
|
||||||
|
WinToast::instance()->setAppUserModelId(TEXT(APP_USER_MODEL_ID));
|
||||||
|
pimpl->isInit = WinToast::instance()->initialize();
|
||||||
|
#endif
|
||||||
|
return pimpl->isInit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CNotification::clear()
|
||||||
|
{
|
||||||
|
if (pimpl->isInit == 1)
|
||||||
|
#ifdef __linux__
|
||||||
|
pimpl->clear();
|
||||||
|
#else
|
||||||
|
WinToast::instance()->clear();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CNotification::show(const QString &msg, const QString &content, DlgBtns dlgBtns, const FnVoidInt &callback)
|
||||||
|
{
|
||||||
|
#ifdef __linux__
|
||||||
|
if (!isNotificationsEnabled())
|
||||||
|
return false;
|
||||||
|
QString lpText = QTextDocumentFragment::fromHtml(msg).toPlainText();
|
||||||
|
NotifyNotification *ntf = notify_notification_new(lpText.toLocal8Bit().data(), content.toLocal8Bit().data(), NULL);
|
||||||
|
g_signal_connect(G_OBJECT(ntf), "closed", G_CALLBACK(on_close), (void*)&pimpl->ntfMap);
|
||||||
|
notify_notification_set_urgency(ntf, NotifyUrgency::NOTIFY_URGENCY_NORMAL);
|
||||||
|
notify_notification_set_timeout(ntf, NOTIF_TIMEOUT_MS);
|
||||||
|
pimpl->ntfMap[ntf] = callback;
|
||||||
|
|
||||||
|
if (callback) {
|
||||||
|
switch (dlgBtns) {
|
||||||
|
case DlgBtns::mbInslaterRestart:
|
||||||
|
addAction("inslater", TEXT_INSLATER.c_str());
|
||||||
|
addAction("restart", TEXT_RESTART.c_str());
|
||||||
|
break;
|
||||||
|
case DlgBtns::mbSkipRemindInstall:
|
||||||
|
addAction("skip", TEXT_SKIP.c_str());
|
||||||
|
addAction("remind", TEXT_REMIND.c_str());
|
||||||
|
addAction("install", TEXT_INSTALL.c_str());
|
||||||
|
break;
|
||||||
|
case DlgBtns::mbSkipRemindSaveandinstall:
|
||||||
|
addAction("skip", TEXT_SKIP.c_str());
|
||||||
|
addAction("remind", TEXT_REMIND.c_str());
|
||||||
|
addAction("saveins", TEXT_SAVEANDINS.c_str());
|
||||||
|
break;
|
||||||
|
case DlgBtns::mbSkipRemindDownload:
|
||||||
|
addAction("skip", TEXT_SKIP.c_str());
|
||||||
|
addAction("remind", TEXT_REMIND.c_str());
|
||||||
|
addAction("download", TEXT_DOWNLOAD.c_str());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return notify_notification_show(ntf, NULL);
|
||||||
|
#else
|
||||||
|
std::wstring lpText = QTextDocumentFragment::fromHtml(msg).toPlainText().toStdWString();
|
||||||
|
std::wstring lpContent = content.toStdWString();
|
||||||
|
|
||||||
|
WinToastTemplate tmpl(WinToastTemplate::WinToastTemplateType::ImageAndText02);
|
||||||
|
tmpl.setTextField(lpText, WinToastTemplate::FirstLine);
|
||||||
|
tmpl.setTextField(lpContent, WinToastTemplate::SecondLine);
|
||||||
|
const QString appIcon = QCoreApplication::applicationDirPath() + "/app.ico";
|
||||||
|
if (QFileInfo::exists(appIcon))
|
||||||
|
tmpl.setImagePath(appIcon.toStdWString());
|
||||||
|
tmpl.setAudioPath(WinToastTemplate::AudioSystemFile::Mail);
|
||||||
|
tmpl.setDuration(WinToastTemplate::Duration::System);
|
||||||
|
tmpl.setExpiration(NOTIF_TIMEOUT_MS);
|
||||||
|
|
||||||
|
switch (dlgBtns) {
|
||||||
|
case DlgBtns::mbInslaterRestart:
|
||||||
|
tmpl.addAction(TEXT_INSLATER);
|
||||||
|
tmpl.addAction(TEXT_RESTART);
|
||||||
|
break;
|
||||||
|
case DlgBtns::mbSkipRemindInstall:
|
||||||
|
tmpl.addAction(TEXT_SKIP);
|
||||||
|
tmpl.addAction(TEXT_REMIND);
|
||||||
|
tmpl.addAction(TEXT_INSTALL);
|
||||||
|
break;
|
||||||
|
case DlgBtns::mbSkipRemindSaveandinstall:
|
||||||
|
tmpl.addAction(TEXT_SKIP);
|
||||||
|
tmpl.addAction(TEXT_REMIND);
|
||||||
|
tmpl.addAction(TEXT_SAVEANDINS);
|
||||||
|
break;
|
||||||
|
case DlgBtns::mbSkipRemindDownload:
|
||||||
|
tmpl.addAction(TEXT_SKIP);
|
||||||
|
tmpl.addAction(TEXT_REMIND);
|
||||||
|
tmpl.addAction(TEXT_DOWNLOAD);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return WinToast::instance()->showToast(tmpl, new ToastHandler(dlgBtns, callback)) > -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
67
win-linux/src/components/cnotification.h
Normal file
67
win-linux/src/components/cnotification.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* (c) Copyright Ascensio System SIA 2010-2019
|
||||||
|
*
|
||||||
|
* This program is a free software product. You can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
||||||
|
* version 3 as published by the Free Software Foundation. In accordance with
|
||||||
|
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
|
||||||
|
* that Ascensio System SIA expressly excludes the warranty of non-infringement
|
||||||
|
* of any third-party rights.
|
||||||
|
*
|
||||||
|
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
||||||
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
||||||
|
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||||
|
*
|
||||||
|
* You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
|
||||||
|
* street, Riga, Latvia, EU, LV-1050.
|
||||||
|
*
|
||||||
|
* The interactive user interfaces in modified source and object code versions
|
||||||
|
* of the Program must display Appropriate Legal Notices, as required under
|
||||||
|
* Section 5 of the GNU AGPL version 3.
|
||||||
|
*
|
||||||
|
* Pursuant to Section 7(b) of the License you must retain the original Product
|
||||||
|
* logo when distributing the program. Pursuant to Section 7(e) we decline to
|
||||||
|
* grant you any rights under trademark law for use of our trademarks.
|
||||||
|
*
|
||||||
|
* All the Product's GUI elements, including illustrations and icon sets, as
|
||||||
|
* well as technical writing content are licensed under the terms of the
|
||||||
|
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
|
||||||
|
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CNOTIFICATION_H
|
||||||
|
#define CNOTIFICATION_H
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# include "platform_win/updatedialog.h"
|
||||||
|
#else
|
||||||
|
# include "platform_linux/updatedialog.h"
|
||||||
|
#endif
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#define mbNone WinDlg::DlgBtns(-1)
|
||||||
|
#define NOTIF_FAILED -2
|
||||||
|
//#define NOTIF_DISMISSED -3
|
||||||
|
|
||||||
|
|
||||||
|
typedef std::function<void(int)> FnVoidInt;
|
||||||
|
|
||||||
|
class CNotification {
|
||||||
|
public:
|
||||||
|
CNotification(const CNotification&) = delete;
|
||||||
|
CNotification& operator=(const CNotification&) = delete;
|
||||||
|
static CNotification& instance();
|
||||||
|
bool init();
|
||||||
|
bool show(const QString &msg, const QString &content, WinDlg::DlgBtns dlgBtns = mbNone, const FnVoidInt &callback = nullptr);
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
private:
|
||||||
|
CNotification();
|
||||||
|
~CNotification();
|
||||||
|
|
||||||
|
class CNotificationPrivate;
|
||||||
|
CNotificationPrivate *pimpl = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CNOTIFICATION_H
|
||||||
@ -402,6 +402,7 @@ void CUpdateManager::init()
|
|||||||
if (m_interval < MINIMUM_INTERVAL)
|
if (m_interval < MINIMUM_INTERVAL)
|
||||||
m_interval = MINIMUM_INTERVAL;
|
m_interval = MINIMUM_INTERVAL;
|
||||||
reg_user.endGroup();
|
reg_user.endGroup();
|
||||||
|
m_notificationSupported = CNotification::instance().init();
|
||||||
|
|
||||||
m_socket->onMessageReceived([this](void *data, size_t) {
|
m_socket->onMessageReceived([this](void *data, size_t) {
|
||||||
vector<tstring> params;
|
vector<tstring> params;
|
||||||
@ -879,19 +880,33 @@ void CUpdateManager::onCheckFinished(bool error, bool updateExist, const QString
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CUpdateManager::showUpdateMessage(QWidget *parent) {
|
void CUpdateManager::showUpdateMessage(QWidget *parent, bool forceModal, int result) {
|
||||||
QString name = (m_packageData->object == "app") ? QString(WINDOW_NAME) : QString(SERVICE_NAME);
|
if (result == DLG_RESULT_NONE) {
|
||||||
QString curr_version = (m_packageData->object == "app") ? QString(VER_FILEVERSION_STR) :
|
QString name = (m_packageData->object == "app") ? QString(WINDOW_NAME) : QString(SERVICE_NAME);
|
||||||
getFileVersion(QStrToTStr(qApp->applicationDirPath()) + DAEMON_NAME);
|
QString curr_version = (m_packageData->object == "app") ? QString(VER_FILEVERSION_STR) :
|
||||||
QString text = m_packageData->isInstallable ? tr("Would you like to download update now?") :
|
getFileVersion(QStrToTStr(qApp->applicationDirPath()) + DAEMON_NAME);
|
||||||
tr("The current version does not support installing this update directly. "
|
QString text = m_packageData->isInstallable ? tr("Would you like to download update now?") :
|
||||||
"To install updates, you can download the required package from the official website.");
|
tr("The current version does not support installing this update directly. "
|
||||||
int result = WinDlg::showDialog(parent, tr("Update is available"),
|
"To install updates, you can download the required package from the official website.");
|
||||||
|
QString title = tr("Update is available");
|
||||||
|
if (!forceModal && m_notificationSupported) {
|
||||||
|
if (CNotification::instance().show(title,
|
||||||
|
QString("%1\n%2: %3\n%4: %5").arg(name, tr("Current version"),
|
||||||
|
curr_version, tr("New version"), m_packageData->version),
|
||||||
|
WinDlg::DlgBtns::mbSkipRemindDownload, [=](int res) {
|
||||||
|
QMetaObject::invokeMethod(this, "showUpdateMessage", Qt::QueuedConnection, Q_ARG(QWidget*, parent), Q_ARG(bool, res == NOTIF_FAILED), Q_ARG(int, res));
|
||||||
|
})) {
|
||||||
|
__UNLOCK
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = WinDlg::showDialog(parent, title,
|
||||||
QString("%1\n%2: %3\n%4: %5\n%6 (%7 MB)").arg(name, tr("Current version"),
|
QString("%1\n%2: %3\n%4: %5\n%6 (%7 MB)").arg(name, tr("Current version"),
|
||||||
curr_version, tr("New version"), m_packageData->version,
|
curr_version, tr("New version"), m_packageData->version,
|
||||||
text, m_packageData->fileSize),
|
text, m_packageData->fileSize),
|
||||||
WinDlg::DlgBtns::mbSkipRemindDownload);
|
WinDlg::DlgBtns::mbSkipRemindDownload);
|
||||||
__UNLOCK
|
__UNLOCK
|
||||||
|
}
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case WinDlg::DLG_RESULT_DOWNLOAD:
|
case WinDlg::DLG_RESULT_DOWNLOAD:
|
||||||
if (m_packageData->isInstallable)
|
if (m_packageData->isInstallable)
|
||||||
@ -910,17 +925,31 @@ void CUpdateManager::showUpdateMessage(QWidget *parent) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CUpdateManager::showStartInstallMessage(QWidget *parent)
|
void CUpdateManager::showStartInstallMessage(QWidget *parent, bool forceModal, int result)
|
||||||
{
|
{
|
||||||
QString name = (m_packageData->object == "app") ? QString(WINDOW_NAME) : QString(SERVICE_NAME);
|
if (result == DLG_RESULT_NONE) {
|
||||||
QString curr_version = (m_packageData->object == "app") ? QString(VER_FILEVERSION_STR) :
|
QString name = (m_packageData->object == "app") ? QString(WINDOW_NAME) : QString(SERVICE_NAME);
|
||||||
getFileVersion(QStrToTStr(qApp->applicationDirPath()) + DAEMON_NAME);
|
QString curr_version = (m_packageData->object == "app") ? QString(VER_FILEVERSION_STR) :
|
||||||
int result = WinDlg::showDialog(parent, tr("Update is ready to install"),
|
getFileVersion(QStrToTStr(qApp->applicationDirPath()) + DAEMON_NAME);
|
||||||
|
QString title = tr("Update is ready to install");
|
||||||
|
if (!forceModal && m_notificationSupported) {
|
||||||
|
if (CNotification::instance().show(title,
|
||||||
|
QString("%1\n%2: %3\n%4: %5").arg(name, tr("Current version"),
|
||||||
|
curr_version, tr("New version"), m_packageData->version),
|
||||||
|
WinDlg::DlgBtns::mbInslaterRestart, [=](int res) {
|
||||||
|
QMetaObject::invokeMethod(this, "showStartInstallMessage", Qt::QueuedConnection, Q_ARG(QWidget*, parent), Q_ARG(bool, res == NOTIF_FAILED), Q_ARG(int, res));
|
||||||
|
})) {
|
||||||
|
__UNLOCK
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = WinDlg::showDialog(parent, title,
|
||||||
QString("%1\n%2: %3\n%4: %5\n%6").arg(name, tr("Current version"),
|
QString("%1\n%2: %3\n%4: %5\n%6").arg(name, tr("Current version"),
|
||||||
curr_version, tr("New version"), m_packageData->version,
|
curr_version, tr("New version"), m_packageData->version,
|
||||||
tr("To finish updating, restart the app")),
|
tr("To finish updating, restart the app")),
|
||||||
WinDlg::DlgBtns::mbInslaterRestart);
|
WinDlg::DlgBtns::mbInslaterRestart);
|
||||||
__UNLOCK
|
__UNLOCK
|
||||||
|
}
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case WinDlg::DLG_RESULT_RESTART: {
|
case WinDlg::DLG_RESULT_RESTART: {
|
||||||
m_startUpdateOnClose = true;
|
m_startUpdateOnClose = true;
|
||||||
|
|||||||
@ -50,6 +50,8 @@
|
|||||||
# define TStrToQStr(a) QString::fromStdString(a)
|
# define TStrToQStr(a) QString::fromStdString(a)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define DLG_RESULT_NONE -2
|
||||||
|
|
||||||
using std::wstring;
|
using std::wstring;
|
||||||
|
|
||||||
enum UpdateMode {
|
enum UpdateMode {
|
||||||
@ -115,6 +117,7 @@ private:
|
|||||||
|
|
||||||
bool m_startUpdateOnClose = false,
|
bool m_startUpdateOnClose = false,
|
||||||
m_restartAfterUpdate = false,
|
m_restartAfterUpdate = false,
|
||||||
|
m_notificationSupported = false,
|
||||||
m_manualCheck = false,
|
m_manualCheck = false,
|
||||||
m_lock = false;
|
m_lock = false;
|
||||||
|
|
||||||
@ -135,9 +138,9 @@ private:
|
|||||||
private slots:
|
private slots:
|
||||||
void onCheckFinished(bool error, bool updateExist, const QString &version, const QString &changelog);
|
void onCheckFinished(bool error, bool updateExist, const QString &version, const QString &changelog);
|
||||||
void onLoadCheckFinished(const QString &json);
|
void onLoadCheckFinished(const QString &json);
|
||||||
void showUpdateMessage(QWidget *parent);
|
void showUpdateMessage(QWidget *parent, bool forceModal = false, int result = DLG_RESULT_NONE);
|
||||||
void onLoadUpdateFinished(const QString &filePath);
|
void onLoadUpdateFinished(const QString &filePath);
|
||||||
void showStartInstallMessage(QWidget *parent);
|
void showStartInstallMessage(QWidget *parent, bool forceModal = false, int result = DLG_RESULT_NONE);
|
||||||
void onProgressSlot(const int percent);
|
void onProgressSlot(const int percent);
|
||||||
void onUnzipProgressSlot(const int percent);
|
void onUnzipProgressSlot(const int percent);
|
||||||
void onError(const QString &error);
|
void onError(const QString &error);
|
||||||
|
|||||||
1490
win-linux/src/platform_win/wintoastlib.cpp
Normal file
1490
win-linux/src/platform_win/wintoastlib.cpp
Normal file
File diff suppressed because it is too large
Load Diff
314
win-linux/src/platform_win/wintoastlib.h
Normal file
314
win-linux/src/platform_win/wintoastlib.h
Normal file
@ -0,0 +1,314 @@
|
|||||||
|
/**
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016-2023 WinToast v1.3.0 - Mohammed Boujemaoui <mohabouje@gmail.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WINTOASTLIB_H
|
||||||
|
#define WINTOASTLIB_H
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <sdkddkver.h>
|
||||||
|
#include <WinUser.h>
|
||||||
|
#include <ShObjIdl.h>
|
||||||
|
#include <wrl/implements.h>
|
||||||
|
#include <wrl/event.h>
|
||||||
|
#include <windows.ui.notifications.h>
|
||||||
|
#include <strsafe.h>
|
||||||
|
#include <Psapi.h>
|
||||||
|
#include <ShlObj.h>
|
||||||
|
#include <roapi.h>
|
||||||
|
#include <propvarutil.h>
|
||||||
|
#include <functiondiscoverykeys.h>
|
||||||
|
#include <winstring.h>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
using namespace Microsoft::WRL;
|
||||||
|
using namespace ABI::Windows::Data::Xml::Dom;
|
||||||
|
using namespace ABI::Windows::Foundation;
|
||||||
|
using namespace ABI::Windows::UI::Notifications;
|
||||||
|
using namespace Windows::Foundation;
|
||||||
|
|
||||||
|
namespace WinToastLib {
|
||||||
|
|
||||||
|
class IWinToastHandler {
|
||||||
|
public:
|
||||||
|
enum WinToastDismissalReason {
|
||||||
|
UserCanceled = ToastDismissalReason::ToastDismissalReason_UserCanceled,
|
||||||
|
ApplicationHidden = ToastDismissalReason::ToastDismissalReason_ApplicationHidden,
|
||||||
|
TimedOut = ToastDismissalReason::ToastDismissalReason_TimedOut
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual ~IWinToastHandler() = default;
|
||||||
|
virtual void toastActivated() const = 0;
|
||||||
|
virtual void toastActivated(int actionIndex) const = 0;
|
||||||
|
virtual void toastActivated(const char* response) const = 0;
|
||||||
|
virtual void toastDismissed(WinToastDismissalReason state) const = 0;
|
||||||
|
virtual void toastFailed() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class WinToastTemplate {
|
||||||
|
public:
|
||||||
|
enum class Scenario { Default, Alarm, IncomingCall, Reminder };
|
||||||
|
enum Duration { System, Short, Long };
|
||||||
|
enum AudioOption { Default = 0, Silent, Loop };
|
||||||
|
enum TextField { FirstLine = 0, SecondLine, ThirdLine };
|
||||||
|
|
||||||
|
enum WinToastTemplateType {
|
||||||
|
ImageAndText01 = ToastTemplateType::ToastTemplateType_ToastImageAndText01,
|
||||||
|
ImageAndText02 = ToastTemplateType::ToastTemplateType_ToastImageAndText02,
|
||||||
|
ImageAndText03 = ToastTemplateType::ToastTemplateType_ToastImageAndText03,
|
||||||
|
ImageAndText04 = ToastTemplateType::ToastTemplateType_ToastImageAndText04,
|
||||||
|
Text01 = ToastTemplateType::ToastTemplateType_ToastText01,
|
||||||
|
Text02 = ToastTemplateType::ToastTemplateType_ToastText02,
|
||||||
|
Text03 = ToastTemplateType::ToastTemplateType_ToastText03,
|
||||||
|
Text04 = ToastTemplateType::ToastTemplateType_ToastText04
|
||||||
|
};
|
||||||
|
|
||||||
|
enum AudioSystemFile {
|
||||||
|
DefaultSound,
|
||||||
|
IM,
|
||||||
|
Mail,
|
||||||
|
Reminder,
|
||||||
|
SMS,
|
||||||
|
Alarm,
|
||||||
|
Alarm2,
|
||||||
|
Alarm3,
|
||||||
|
Alarm4,
|
||||||
|
Alarm5,
|
||||||
|
Alarm6,
|
||||||
|
Alarm7,
|
||||||
|
Alarm8,
|
||||||
|
Alarm9,
|
||||||
|
Alarm10,
|
||||||
|
Call,
|
||||||
|
Call1,
|
||||||
|
Call2,
|
||||||
|
Call3,
|
||||||
|
Call4,
|
||||||
|
Call5,
|
||||||
|
Call6,
|
||||||
|
Call7,
|
||||||
|
Call8,
|
||||||
|
Call9,
|
||||||
|
Call10,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum CropHint {
|
||||||
|
Square,
|
||||||
|
Circle,
|
||||||
|
};
|
||||||
|
|
||||||
|
WinToastTemplate(_In_ WinToastTemplateType type = WinToastTemplateType::ImageAndText02);
|
||||||
|
~WinToastTemplate();
|
||||||
|
|
||||||
|
void setFirstLine(_In_ std::wstring const& text);
|
||||||
|
void setSecondLine(_In_ std::wstring const& text);
|
||||||
|
void setThirdLine(_In_ std::wstring const& text);
|
||||||
|
void setTextField(_In_ std::wstring const& txt, _In_ TextField pos);
|
||||||
|
void setAttributionText(_In_ std::wstring const& attributionText);
|
||||||
|
void setImagePath(_In_ std::wstring const& imgPath, _In_ CropHint cropHint = CropHint::Square);
|
||||||
|
void setHeroImagePath(_In_ std::wstring const& imgPath, _In_ bool inlineImage = false);
|
||||||
|
void setAudioPath(_In_ WinToastTemplate::AudioSystemFile audio);
|
||||||
|
void setAudioPath(_In_ std::wstring const& audioPath);
|
||||||
|
void setAudioOption(_In_ WinToastTemplate::AudioOption audioOption);
|
||||||
|
void setDuration(_In_ Duration duration);
|
||||||
|
void setExpiration(_In_ INT64 millisecondsFromNow);
|
||||||
|
void setScenario(_In_ Scenario scenario);
|
||||||
|
void addAction(_In_ std::wstring const& label);
|
||||||
|
void addInput();
|
||||||
|
|
||||||
|
std::size_t textFieldsCount() const;
|
||||||
|
std::size_t actionsCount() const;
|
||||||
|
bool hasImage() const;
|
||||||
|
bool hasHeroImage() const;
|
||||||
|
std::vector<std::wstring> const& textFields() const;
|
||||||
|
std::wstring const& textField(_In_ TextField pos) const;
|
||||||
|
std::wstring const& actionLabel(_In_ std::size_t pos) const;
|
||||||
|
std::wstring const& imagePath() const;
|
||||||
|
std::wstring const& heroImagePath() const;
|
||||||
|
std::wstring const& audioPath() const;
|
||||||
|
std::wstring const& attributionText() const;
|
||||||
|
std::wstring const& scenario() const;
|
||||||
|
INT64 expiration() const;
|
||||||
|
WinToastTemplateType type() const;
|
||||||
|
WinToastTemplate::AudioOption audioOption() const;
|
||||||
|
Duration duration() const;
|
||||||
|
bool isToastGeneric() const;
|
||||||
|
bool isInlineHeroImage() const;
|
||||||
|
bool isCropHintCircle() const;
|
||||||
|
bool isInput() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _hasInput{false};
|
||||||
|
|
||||||
|
std::vector<std::wstring> _textFields{};
|
||||||
|
std::vector<std::wstring> _actions{};
|
||||||
|
std::wstring _imagePath{};
|
||||||
|
std::wstring _heroImagePath{};
|
||||||
|
bool _inlineHeroImage{false};
|
||||||
|
std::wstring _audioPath{};
|
||||||
|
std::wstring _attributionText{};
|
||||||
|
std::wstring _scenario{L"Default"};
|
||||||
|
INT64 _expiration{0};
|
||||||
|
AudioOption _audioOption{WinToastTemplate::AudioOption::Default};
|
||||||
|
WinToastTemplateType _type{WinToastTemplateType::Text01};
|
||||||
|
Duration _duration{Duration::System};
|
||||||
|
CropHint _cropHint{CropHint::Square};
|
||||||
|
};
|
||||||
|
|
||||||
|
class WinToast {
|
||||||
|
public:
|
||||||
|
enum WinToastError {
|
||||||
|
NoError = 0,
|
||||||
|
NotInitialized,
|
||||||
|
SystemNotSupported,
|
||||||
|
ShellLinkNotCreated,
|
||||||
|
InvalidAppUserModelID,
|
||||||
|
InvalidParameters,
|
||||||
|
InvalidHandler,
|
||||||
|
NotDisplayed,
|
||||||
|
UnknownError
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ShortcutResult {
|
||||||
|
SHORTCUT_UNCHANGED = 0,
|
||||||
|
SHORTCUT_WAS_CHANGED = 1,
|
||||||
|
SHORTCUT_WAS_CREATED = 2,
|
||||||
|
|
||||||
|
SHORTCUT_MISSING_PARAMETERS = -1,
|
||||||
|
SHORTCUT_INCOMPATIBLE_OS = -2,
|
||||||
|
SHORTCUT_COM_INIT_FAILURE = -3,
|
||||||
|
SHORTCUT_CREATE_FAILED = -4
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ShortcutPolicy {
|
||||||
|
/* Don't check, create, or modify a shortcut. */
|
||||||
|
SHORTCUT_POLICY_IGNORE = 0,
|
||||||
|
/* Require a shortcut with matching AUMI, don't create or modify an existing one. */
|
||||||
|
SHORTCUT_POLICY_REQUIRE_NO_CREATE = 1,
|
||||||
|
/* Require a shortcut with matching AUMI, create if missing, modify if not matching. This is the default. */
|
||||||
|
SHORTCUT_POLICY_REQUIRE_CREATE = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
WinToast(void);
|
||||||
|
virtual ~WinToast();
|
||||||
|
static WinToast* instance();
|
||||||
|
static bool isCompatible();
|
||||||
|
static bool isSupportingModernFeatures();
|
||||||
|
static bool isWin10AnniversaryOrHigher();
|
||||||
|
static std::wstring configureAUMI(_In_ std::wstring const& companyName, _In_ std::wstring const& productName,
|
||||||
|
_In_ std::wstring const& subProduct = std::wstring(),
|
||||||
|
_In_ std::wstring const& versionInformation = std::wstring());
|
||||||
|
static std::wstring const& strerror(_In_ WinToastError error);
|
||||||
|
bool initialize(_Out_opt_ WinToastError* error = nullptr);
|
||||||
|
bool isInitialized() const;
|
||||||
|
bool hideToast(_In_ INT64 id);
|
||||||
|
INT64 showToast(_In_ WinToastTemplate const& toast, _In_ IWinToastHandler* eventHandler,
|
||||||
|
_Out_opt_ WinToastError* error = nullptr);
|
||||||
|
void clear();
|
||||||
|
enum ShortcutResult createShortcut();
|
||||||
|
|
||||||
|
std::wstring const& appName() const;
|
||||||
|
std::wstring const& appUserModelId() const;
|
||||||
|
void setAppUserModelId(_In_ std::wstring const& aumi);
|
||||||
|
void setAppName(_In_ std::wstring const& appName);
|
||||||
|
void setShortcutPolicy(_In_ ShortcutPolicy policy);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
struct NotifyData {
|
||||||
|
NotifyData(){};
|
||||||
|
NotifyData(_In_ ComPtr<IToastNotification> notify, _In_ EventRegistrationToken activatedToken,
|
||||||
|
_In_ EventRegistrationToken dismissedToken, _In_ EventRegistrationToken failedToken) :
|
||||||
|
_notify(notify), _activatedToken(activatedToken), _dismissedToken(dismissedToken), _failedToken(failedToken) {}
|
||||||
|
|
||||||
|
~NotifyData() {
|
||||||
|
RemoveTokens();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveTokens() {
|
||||||
|
if (!_readyForDeletion) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_previouslyTokenRemoved) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_notify.Get()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_notify->remove_Activated(_activatedToken);
|
||||||
|
_notify->remove_Dismissed(_dismissedToken);
|
||||||
|
_notify->remove_Failed(_failedToken);
|
||||||
|
_previouslyTokenRemoved = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void markAsReadyForDeletion() {
|
||||||
|
_readyForDeletion = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isReadyForDeletion() const {
|
||||||
|
return _readyForDeletion;
|
||||||
|
}
|
||||||
|
|
||||||
|
IToastNotification* notification() {
|
||||||
|
return _notify.Get();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ComPtr<IToastNotification> _notify{nullptr};
|
||||||
|
EventRegistrationToken _activatedToken{};
|
||||||
|
EventRegistrationToken _dismissedToken{};
|
||||||
|
EventRegistrationToken _failedToken{};
|
||||||
|
bool _readyForDeletion{false};
|
||||||
|
bool _previouslyTokenRemoved{false};
|
||||||
|
};
|
||||||
|
|
||||||
|
bool _isInitialized{false};
|
||||||
|
bool _hasCoInitialized{false};
|
||||||
|
ShortcutPolicy _shortcutPolicy{SHORTCUT_POLICY_REQUIRE_CREATE};
|
||||||
|
std::wstring _appName{};
|
||||||
|
std::wstring _aumi{};
|
||||||
|
std::map<INT64, NotifyData> _buffer{};
|
||||||
|
|
||||||
|
void markAsReadyForDeletion(_In_ INT64 id);
|
||||||
|
HRESULT validateShellLinkHelper(_Out_ bool& wasChanged);
|
||||||
|
HRESULT createShellLinkHelper();
|
||||||
|
HRESULT setImageFieldHelper(_In_ IXmlDocument* xml, _In_ std::wstring const& path, _In_ bool isToastGeneric, bool isCropHintCircle);
|
||||||
|
HRESULT setHeroImageHelper(_In_ IXmlDocument* xml, _In_ std::wstring const& path, _In_ bool isInlineImage);
|
||||||
|
HRESULT setBindToastGenericHelper(_In_ IXmlDocument* xml);
|
||||||
|
HRESULT
|
||||||
|
setAudioFieldHelper(_In_ IXmlDocument* xml, _In_ std::wstring const& path,
|
||||||
|
_In_opt_ WinToastTemplate::AudioOption option = WinToastTemplate::AudioOption::Default);
|
||||||
|
HRESULT setTextFieldHelper(_In_ IXmlDocument* xml, _In_ std::wstring const& text, _In_ UINT32 pos);
|
||||||
|
HRESULT setAttributionTextFieldHelper(_In_ IXmlDocument* xml, _In_ std::wstring const& text);
|
||||||
|
HRESULT addActionHelper(_In_ IXmlDocument* xml, _In_ std::wstring const& action, _In_ std::wstring const& arguments);
|
||||||
|
HRESULT addDurationHelper(_In_ IXmlDocument* xml, _In_ std::wstring const& duration);
|
||||||
|
HRESULT addScenarioHelper(_In_ IXmlDocument* xml, _In_ std::wstring const& scenario);
|
||||||
|
HRESULT addInputHelper(_In_ IXmlDocument* xml);
|
||||||
|
ComPtr<IToastNotifier> notifier(_In_ bool* succeded) const;
|
||||||
|
void setError(_Out_opt_ WinToastError* error, _In_ WinToastError value);
|
||||||
|
};
|
||||||
|
} // namespace WinToastLib
|
||||||
|
#endif // WINTOASTLIB_H
|
||||||
@ -989,6 +989,12 @@ namespace WindowHelper {
|
|||||||
else
|
else
|
||||||
if (env.indexOf("KDE") != -1)
|
if (env.indexOf("KDE") != -1)
|
||||||
desktop_env = KDE;
|
desktop_env = KDE;
|
||||||
|
else
|
||||||
|
if (env.indexOf("XFCE") != -1)
|
||||||
|
desktop_env = XFCE;
|
||||||
|
else
|
||||||
|
if (env.indexOf("Cinnamon") != -1)
|
||||||
|
desktop_env = CINNAMON;
|
||||||
else desktop_env = OTHER;
|
else desktop_env = OTHER;
|
||||||
}
|
}
|
||||||
return desktop_env;
|
return desktop_env;
|
||||||
|
|||||||
@ -156,6 +156,8 @@ namespace WindowHelper {
|
|||||||
UNITY = 0,
|
UNITY = 0,
|
||||||
GNOME,
|
GNOME,
|
||||||
KDE,
|
KDE,
|
||||||
|
XFCE,
|
||||||
|
CINNAMON,
|
||||||
OTHER
|
OTHER
|
||||||
};
|
};
|
||||||
auto getEnvInfo() -> int;
|
auto getEnvInfo() -> int;
|
||||||
|
|||||||
Reference in New Issue
Block a user