mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 14:17:12 +02:00
Add reply from Windows native notifications.
This commit is contained in:
parent
967e86f4ab
commit
8c71d03959
1 changed files with 135 additions and 25 deletions
|
@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "main/main_session.h"
|
||||
#include "mainwindow.h"
|
||||
#include "windows_quiethours_h.h"
|
||||
#include "styles/style_chat.h"
|
||||
|
||||
#include <QtCore/QOperatingSystemVersion>
|
||||
|
||||
|
@ -32,7 +33,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.Data.Xml.Dom.h>
|
||||
#include <winrt/Windows.UI.Notifications.h>
|
||||
#include <winrt/Windows.UI.Notifications.Management.h>
|
||||
|
||||
HICON qt_pixmapToWinHICON(const QPixmap &);
|
||||
|
||||
|
@ -48,6 +48,43 @@ namespace Notifications {
|
|||
#ifndef __MINGW32__
|
||||
namespace {
|
||||
|
||||
constexpr auto kNotificationTemplate = LR"(
|
||||
<toast launch="action=open">
|
||||
<visual>
|
||||
<binding template="ToastGeneric">
|
||||
<image placement="appLogoOverride" hint-crop="circle" src=""/>
|
||||
<text hint-maxLines="1"></text>
|
||||
<text></text>
|
||||
<text></text>
|
||||
</binding>
|
||||
</visual>
|
||||
<actions>
|
||||
<input id="fastReply" type="text" placeHolderContent=""/>
|
||||
<action
|
||||
content="Send"
|
||||
arguments="action=reply"
|
||||
activationType="background"
|
||||
imageUri=""
|
||||
hint-inputId="fastReply"/>
|
||||
</actions>
|
||||
<audio silent="true"/>
|
||||
</toast>
|
||||
)";
|
||||
|
||||
constexpr auto kNotificationTemplateSmall = LR"(
|
||||
<toast launch="action=open">
|
||||
<visual>
|
||||
<binding template="ToastGeneric">
|
||||
<image placement="appLogoOverride" hint-crop="circle" src=""/>
|
||||
<text hint-maxLines="1"></text>
|
||||
<text></text>
|
||||
<text></text>
|
||||
</binding>
|
||||
</visual>
|
||||
<audio silent="true"/>
|
||||
</toast>
|
||||
)";
|
||||
|
||||
bool init() {
|
||||
if (!IsWindows8OrGreater()) {
|
||||
return false;
|
||||
|
@ -100,6 +137,28 @@ void SetImageSrc(const XmlDocument &toastXml, const std::wstring &path) {
|
|||
L"file:///" + path);
|
||||
}
|
||||
|
||||
// Throws.
|
||||
void SetReplyIconSrc(const XmlDocument &toastXml, const std::wstring &path) {
|
||||
const auto nodeList = toastXml.GetElementsByTagName(L"action");
|
||||
const auto attributes = nodeList.Item(0).Attributes();
|
||||
return SetNodeValueString(
|
||||
toastXml,
|
||||
attributes.GetNamedItem(L"imageUri"),
|
||||
L"file:///" + path);
|
||||
}
|
||||
|
||||
// Throws.
|
||||
void SetReplyPlaceholder(
|
||||
const XmlDocument &toastXml,
|
||||
const std::wstring &placeholder) {
|
||||
const auto nodeList = toastXml.GetElementsByTagName(L"input");
|
||||
const auto attributes = nodeList.Item(0).Attributes();
|
||||
return SetNodeValueString(
|
||||
toastXml,
|
||||
attributes.GetNamedItem(L"placeHolderContent"),
|
||||
placeholder);
|
||||
}
|
||||
|
||||
auto Checked = false;
|
||||
auto InitSucceeded = false;
|
||||
|
||||
|
@ -340,8 +399,10 @@ private:
|
|||
const QString &msg,
|
||||
bool hideNameAndPhoto,
|
||||
bool hideReplyButton);
|
||||
[[nodiscard]] std::wstring ensureSendButtonIcon();
|
||||
|
||||
Window::Notifications::CachedUserpics _cachedUserpics;
|
||||
std::wstring _sendButtonIconPath;
|
||||
|
||||
std::shared_ptr<Manager*> _guarded;
|
||||
ToastNotifier _notifier = nullptr;
|
||||
|
@ -469,6 +530,15 @@ bool Manager::Private::showNotification(
|
|||
}).value_or(false);
|
||||
}
|
||||
|
||||
std::wstring Manager::Private::ensureSendButtonIcon() {
|
||||
if (_sendButtonIconPath.empty()) {
|
||||
const auto path = cWorkingDir() + u"tdata/temp/fast_reply.png"_q;
|
||||
st::historySendIcon.instance(Qt::white, 300).save(path, "PNG");
|
||||
_sendButtonIconPath = path.toStdWString();
|
||||
}
|
||||
return _sendButtonIconPath;
|
||||
}
|
||||
|
||||
bool Manager::Private::showNotificationInTryCatch(
|
||||
not_null<PeerData*> peer,
|
||||
std::shared_ptr<Data::CloudImageView> &userpicView,
|
||||
|
@ -479,17 +549,35 @@ bool Manager::Private::showNotificationInTryCatch(
|
|||
bool hideNameAndPhoto,
|
||||
bool hideReplyButton) {
|
||||
const auto withSubtitle = !subtitle.isEmpty();
|
||||
const auto toastXml = ToastNotificationManager::GetTemplateContent(
|
||||
(withSubtitle
|
||||
? ToastTemplateType::ToastImageAndText04
|
||||
: ToastTemplateType::ToastImageAndText02));
|
||||
SetAudioSilent(toastXml);
|
||||
auto toastXml = XmlDocument();
|
||||
const auto modern = Platform::IsWindows10OrGreater();
|
||||
if (modern) {
|
||||
toastXml.LoadXml(hideReplyButton
|
||||
? kNotificationTemplateSmall
|
||||
: kNotificationTemplate);
|
||||
} else {
|
||||
toastXml = ToastNotificationManager::GetTemplateContent(
|
||||
(withSubtitle
|
||||
? ToastTemplateType::ToastImageAndText04
|
||||
: ToastTemplateType::ToastImageAndText02));
|
||||
SetAudioSilent(toastXml);
|
||||
}
|
||||
|
||||
const auto userpicKey = hideNameAndPhoto
|
||||
? InMemoryKey()
|
||||
: peer->userpicUniqueKey(userpicView);
|
||||
const auto userpicPath = _cachedUserpics.get(userpicKey, peer, userpicView);
|
||||
const auto userpicPathWide = QDir::toNativeSeparators(userpicPath).toStdWString();
|
||||
const auto userpicPath = _cachedUserpics.get(
|
||||
userpicKey,
|
||||
peer,
|
||||
userpicView);
|
||||
const auto userpicPathWide = QDir::toNativeSeparators(
|
||||
userpicPath).toStdWString();
|
||||
if (modern && !hideReplyButton) {
|
||||
SetReplyIconSrc(toastXml, ensureSendButtonIcon());
|
||||
SetReplyPlaceholder(
|
||||
toastXml,
|
||||
tr::lng_message_ph(tr::now).toStdWString());
|
||||
}
|
||||
|
||||
SetImageSrc(toastXml, userpicPathWide);
|
||||
|
||||
|
@ -525,30 +613,52 @@ bool Manager::Private::showNotificationInTryCatch(
|
|||
.full = key,
|
||||
.msgId = msgId
|
||||
};
|
||||
|
||||
auto toast = ToastNotification(toastXml);
|
||||
const auto token1 = toast.Activated([=](
|
||||
const ToastNotification &sender,
|
||||
const winrt::Windows::Foundation::IInspectable &args) {
|
||||
performOnMainQueue([notificationId](Manager *manager) {
|
||||
manager->notificationActivated(notificationId);
|
||||
});
|
||||
const winrt::Windows::Foundation::IInspectable &object) {
|
||||
if (const auto args = object.try_as<ToastActivatedEventArgs>()) {
|
||||
const auto arguments = args.Arguments();
|
||||
const auto userInput = args.UserInput();
|
||||
if (arguments == L"action=reply") {
|
||||
const auto reply = userInput.TryLookup(L"fastReply");
|
||||
const auto data = reply.try_as<IReference<winrt::hstring>>();
|
||||
auto text = data
|
||||
? QString::fromWCharArray(data.GetString().c_str())
|
||||
: QString();
|
||||
if (text.indexOf(QChar('\n')) < 0) {
|
||||
text.replace(QChar('\r'), QChar('\n'));
|
||||
}
|
||||
performOnMainQueue([notificationId, text](Manager *manager) {
|
||||
manager->notificationReplied(notificationId, { text });
|
||||
});
|
||||
} else {
|
||||
performOnMainQueue([notificationId](Manager *manager) {
|
||||
manager->notificationActivated(notificationId);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
performOnMainQueue([notificationId](Manager *manager) {
|
||||
manager->notificationActivated(notificationId);
|
||||
});
|
||||
}
|
||||
});
|
||||
const auto token2 = toast.Dismissed([=](
|
||||
const ToastNotification &sender,
|
||||
const ToastDismissedEventArgs &args) {
|
||||
base::WinRT::Try([&] {
|
||||
switch (args.Reason()) {
|
||||
case ToastDismissalReason::ApplicationHidden:
|
||||
case ToastDismissalReason::TimedOut: // Went to Action Center.
|
||||
break;
|
||||
case ToastDismissalReason::UserCanceled:
|
||||
default:
|
||||
performOnMainQueue([notificationId](Manager *manager) {
|
||||
manager->clearNotification(notificationId);
|
||||
});
|
||||
break;
|
||||
}
|
||||
});
|
||||
const auto reason = args.Reason();
|
||||
switch (reason) {
|
||||
case ToastDismissalReason::ApplicationHidden:
|
||||
case ToastDismissalReason::TimedOut: // Went to Action Center.
|
||||
break;
|
||||
case ToastDismissalReason::UserCanceled:
|
||||
default:
|
||||
performOnMainQueue([notificationId](Manager *manager) {
|
||||
manager->clearNotification(notificationId);
|
||||
});
|
||||
break;
|
||||
}
|
||||
});
|
||||
const auto token3 = toast.Failed([=](
|
||||
const auto &sender,
|
||||
|
|
Loading…
Add table
Reference in a new issue