forked from quickshell/quickshell
service/notifications: add inline-reply action support
Signed-off-by: ipg0 <pyromancy00@gmail.com>
This commit is contained in:
parent
3dfb7d8827
commit
c40074dd56
7 changed files with 79 additions and 3 deletions
|
@ -78,6 +78,29 @@ void Notification::close(NotificationCloseReason::Enum reason) {
|
|||
}
|
||||
}
|
||||
|
||||
void Notification::sendInlineReply(const QString& replyText) {
|
||||
if (!NotificationServer::instance()->support.inlineReply) {
|
||||
qCritical() << "Inline reply support disabled on server";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this->bHasInlineReply) {
|
||||
qCritical() << "Cannot send reply to notification without inline-reply action";
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->isRetained()) {
|
||||
qCritical() << "Cannot send reply to destroyed notification" << this;
|
||||
return;
|
||||
}
|
||||
|
||||
NotificationServer::instance()->NotificationReplied(this->id(), replyText);
|
||||
|
||||
if (!this->bindableResident().value()) {
|
||||
this->close(NotificationCloseReason::Dismissed);
|
||||
}
|
||||
}
|
||||
|
||||
void Notification::updateProperties(
|
||||
const QString& appName,
|
||||
QString appIcon,
|
||||
|
@ -147,17 +170,27 @@ void Notification::updateProperties(
|
|||
this->bImage = imagePath;
|
||||
this->bHints = hints;
|
||||
|
||||
Qt::endPropertyUpdateGroup();
|
||||
|
||||
bool actionsChanged = false;
|
||||
auto deletedActions = QVector<NotificationAction*>();
|
||||
|
||||
if (actions.length() % 2 == 0) {
|
||||
int ai = 0;
|
||||
for (auto i = 0; i != actions.length(); i += 2) {
|
||||
ai = i / 2;
|
||||
const auto& identifier = actions.at(i);
|
||||
const auto& text = actions.at(i + 1);
|
||||
|
||||
if (identifier == "inline-reply" && NotificationServer::instance()->support.inlineReply) {
|
||||
if (this->bHasInlineReply) {
|
||||
qCWarning(logNotifications) << this << '(' << appName << ')'
|
||||
<< "sent an action set with duplicate inline-reply actions.";
|
||||
} else {
|
||||
this->bHasInlineReply = true;
|
||||
this->bInlineReplyPlaceholder = text;
|
||||
}
|
||||
// skip inserting this action into action list
|
||||
continue;
|
||||
}
|
||||
|
||||
auto* action = ai < this->mActions.length() ? this->mActions.at(ai) : nullptr;
|
||||
|
||||
if (action && identifier == action->identifier()) {
|
||||
|
@ -188,6 +221,8 @@ void Notification::updateProperties(
|
|||
<< "sent an action set of an invalid length.";
|
||||
}
|
||||
|
||||
Qt::endPropertyUpdateGroup();
|
||||
|
||||
if (actionsChanged) emit this->actionsChanged();
|
||||
|
||||
for (auto* action: deletedActions) {
|
||||
|
|
|
@ -107,6 +107,12 @@ class Notification
|
|||
///
|
||||
/// This image is often something like a profile picture in instant messaging applications.
|
||||
Q_PROPERTY(QString image READ default NOTIFY imageChanged BINDABLE bindableImage);
|
||||
/// If true, the notification has an inline reply action.
|
||||
///
|
||||
/// A quick reply text field should be displayed and the reply can be sent using @@sendInlineReply().
|
||||
Q_PROPERTY(bool hasInlineReply READ default NOTIFY hasInlineReplyChanged BINDABLE bindableHasInlineReply);
|
||||
/// The placeholder text/button caption for the inline reply.
|
||||
Q_PROPERTY(QString inlineReplyPlaceholder READ default NOTIFY inlineReplyPlaceholderChanged BINDABLE bindableInlineReplyPlaceholder);
|
||||
/// All hints sent by the client application as a javascript object.
|
||||
/// Many common hints are exposed via other properties.
|
||||
Q_PROPERTY(QVariantMap hints READ default NOTIFY hintsChanged BINDABLE bindableHints);
|
||||
|
@ -124,6 +130,12 @@ public:
|
|||
/// explicitly closed by the user.
|
||||
Q_INVOKABLE void dismiss();
|
||||
|
||||
/// Send an inline reply to the notification with an inline reply action.
|
||||
/// > [!WARNING] This method can only be called if
|
||||
/// > @@hasInlineReply is true
|
||||
/// > and the server has @@NotificationServer.inlineReplySupported set to true.
|
||||
Q_INVOKABLE void sendInlineReply(const QString& replyText);
|
||||
|
||||
void updateProperties(
|
||||
const QString& appName,
|
||||
QString appIcon,
|
||||
|
@ -158,6 +170,8 @@ public:
|
|||
[[nodiscard]] QBindable<bool> bindableTransient() const { return &this->bTransient; };
|
||||
[[nodiscard]] QBindable<QString> bindableDesktopEntry() const { return &this->bDesktopEntry; };
|
||||
[[nodiscard]] QBindable<QString> bindableImage() const { return &this->bImage; };
|
||||
[[nodiscard]] QBindable<bool> bindableHasInlineReply() const { return &this->bHasInlineReply; };
|
||||
[[nodiscard]] QBindable<QString> bindableInlineReplyPlaceholder() const { return &this->bInlineReplyPlaceholder; };
|
||||
[[nodiscard]] QBindable<QVariantMap> bindableHints() const { return &this->bHints; };
|
||||
|
||||
[[nodiscard]] NotificationCloseReason::Enum closeReason() const;
|
||||
|
@ -182,6 +196,8 @@ signals:
|
|||
void transientChanged();
|
||||
void desktopEntryChanged();
|
||||
void imageChanged();
|
||||
void hasInlineReplyChanged();
|
||||
void inlineReplyPlaceholderChanged();
|
||||
void hintsChanged();
|
||||
|
||||
private:
|
||||
|
@ -202,6 +218,8 @@ private:
|
|||
Q_OBJECT_BINDABLE_PROPERTY(Notification, bool, bTransient, &Notification::transientChanged);
|
||||
Q_OBJECT_BINDABLE_PROPERTY(Notification, QString, bDesktopEntry, &Notification::desktopEntryChanged);
|
||||
Q_OBJECT_BINDABLE_PROPERTY(Notification, QString, bImage, &Notification::imageChanged);
|
||||
Q_OBJECT_BINDABLE_PROPERTY(Notification, bool, bHasInlineReply, &Notification::hasInlineReplyChanged);
|
||||
Q_OBJECT_BINDABLE_PROPERTY(Notification, QString, bInlineReplyPlaceholder, &Notification::inlineReplyPlaceholderChanged);
|
||||
Q_OBJECT_BINDABLE_PROPERTY(Notification, QVariantMap, bHints, &Notification::hintsChanged);
|
||||
// clang-format on
|
||||
|
||||
|
|
|
@ -38,6 +38,11 @@
|
|||
<arg name="actionKey" type="s" direction="out"/>
|
||||
</signal>
|
||||
|
||||
<signal name="NotificationReplied">
|
||||
<arg name="id" type="u" direction="out"/>
|
||||
<arg name="replyText" type="s" direction="out"/>
|
||||
</signal>
|
||||
|
||||
<signal name="ActivationToken">
|
||||
<arg name="id" type="u" direction="out"/>
|
||||
<arg name="activationToken" type="s" direction="out"/>
|
||||
|
|
|
@ -115,6 +115,15 @@ void NotificationServerQml::setImageSupported(bool imageSupported) {
|
|||
emit this->imageSupportedChanged();
|
||||
}
|
||||
|
||||
bool NotificationServerQml::inlineReplySupported() const { return this->support.inlineReply; }
|
||||
|
||||
void NotificationServerQml::setInlineReplySupported(bool inlineReplySupported) {
|
||||
if (inlineReplySupported == this->support.inlineReply) return;
|
||||
this->support.inlineReply = inlineReplySupported;
|
||||
this->updateSupported();
|
||||
emit this->inlineReplySupportedChanged();
|
||||
}
|
||||
|
||||
QVector<QString> NotificationServerQml::extraHints() const { return this->support.extraHints; }
|
||||
|
||||
void NotificationServerQml::setExtraHints(QVector<QString> extraHints) {
|
||||
|
|
|
@ -65,6 +65,8 @@ class NotificationServerQml: public PostReloadHook {
|
|||
Q_PROPERTY(bool actionIconsSupported READ actionIconsSupported WRITE setActionIconsSupported NOTIFY actionIconsSupportedChanged);
|
||||
/// If the notification server should advertise that it supports images. Defaults to false.
|
||||
Q_PROPERTY(bool imageSupported READ imageSupported WRITE setImageSupported NOTIFY imageSupportedChanged);
|
||||
/// If the notification server should advertise that it supports inline replies. Defaults to false.
|
||||
Q_PROPERTY(bool inlineReplySupported READ inlineReplySupported WRITE setInlineReplySupported NOTIFY inlineReplySupportedChanged);
|
||||
/// All notifications currently tracked by the server.
|
||||
QSDOC_TYPE_OVERRIDE(ObjectModel<qs::service::notifications::Notification>*);
|
||||
Q_PROPERTY(UntypedObjectModel* trackedNotifications READ trackedNotifications NOTIFY trackedNotificationsChanged);
|
||||
|
@ -103,6 +105,9 @@ public:
|
|||
[[nodiscard]] bool imageSupported() const;
|
||||
void setImageSupported(bool imageSupported);
|
||||
|
||||
[[nodiscard]] bool inlineReplySupported() const;
|
||||
void setInlineReplySupported(bool inlineReplySupported);
|
||||
|
||||
[[nodiscard]] QVector<QString> extraHints() const;
|
||||
void setExtraHints(QVector<QString> extraHints);
|
||||
|
||||
|
@ -123,6 +128,7 @@ signals:
|
|||
void actionsSupportedChanged();
|
||||
void actionIconsSupportedChanged();
|
||||
void imageSupportedChanged();
|
||||
void inlineReplySupportedChanged();
|
||||
void extraHintsChanged();
|
||||
void trackedNotificationsChanged();
|
||||
|
||||
|
|
|
@ -155,6 +155,7 @@ QStringList NotificationServer::GetCapabilities() const {
|
|||
}
|
||||
|
||||
if (this->support.image) capabilities += "icon-static";
|
||||
if (this->support.inlineReply) capabilities += "inline-reply";
|
||||
|
||||
capabilities += this->support.extraHints;
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ struct NotificationServerSupport {
|
|||
bool actions = false;
|
||||
bool actionIcons = false;
|
||||
bool image = false;
|
||||
bool inlineReply = false;
|
||||
QVector<QString> extraHints;
|
||||
};
|
||||
|
||||
|
@ -60,6 +61,7 @@ signals:
|
|||
// NOLINTBEGIN
|
||||
void NotificationClosed(quint32 id, quint32 reason);
|
||||
void ActionInvoked(quint32 id, QString action);
|
||||
void NotificationReplied(quint32 id, QString replyText);
|
||||
// NOLINTEND
|
||||
|
||||
private slots:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue