Skip to content

Commit

Permalink
[lipstick] Add explicit handling for minimal-notification styles. Con…
Browse files Browse the repository at this point in the history
…tributes to JB#44743

Add LipstickNotification::presentationStyle and check whether the
notification should be shown based on this style. Also print warnings
when a notification uses a non-recommended configuration.
  • Loading branch information
blammit committed Feb 22, 2019
1 parent dfcffb5 commit 95b5f40
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 19 deletions.
18 changes: 18 additions & 0 deletions src/notifications/lipsticknotification.cpp
Expand Up @@ -166,7 +166,13 @@ QStringList LipstickNotification::actions() const

void LipstickNotification::setActions(const QStringList &actions)
{
PresentationStyle oldStyle = presentationStyle();

m_actions = actions;

if (oldStyle != presentationStyle()) {
emit presentationStyleChanged();
}
}

QVariantHash LipstickNotification::hints() const
Expand All @@ -192,6 +198,7 @@ void LipstickNotification::setHints(const QVariantHash &hints)
QString oldCategory = category();
qreal oldProgress = progress();
bool oldHasProgress = hasProgress();
PresentationStyle oldStyle = presentationStyle();

m_hints = hints;
updateHintValues();
Expand Down Expand Up @@ -242,6 +249,10 @@ void LipstickNotification::setHints(const QVariantHash &hints)
emit progressChanged();
}

if (oldStyle != presentationStyle()) {
emit presentationStyleChanged();
}

emit hintsChanged();
}

Expand Down Expand Up @@ -410,6 +421,13 @@ bool LipstickNotification::hasProgress() const
return m_hints.contains(LipstickNotification::HINT_PROGRESS);
}

LipstickNotification::PresentationStyle LipstickNotification::presentationStyle() const
{
bool hasActions = m_actions.count() > 0;
bool hasMultipleLines = previewSummary().length() > 0 && previewBody().length() > 0;
return hasActions || hasMultipleLines ? LipstickNotification::DefaultNotificationStyle : LipstickNotification::MinimalStyle;
}

quint64 LipstickNotification::internalTimestamp() const
{
return m_timestamp;
Expand Down
12 changes: 12 additions & 0 deletions src/notifications/lipsticknotification.h
Expand Up @@ -55,6 +55,7 @@ class LIPSTICK_EXPORT LipstickNotification : public QObject
Q_PROPERTY(int maxContentLines READ maxContentLines CONSTANT)
Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged)
Q_PROPERTY(bool hasProgress READ hasProgress NOTIFY hasProgressChanged)
Q_PROPERTY(PresentationStyle presentationStyle READ presentationStyle NOTIFY presentationStyleChanged)

public:
//! Standard hint: The urgency level.
Expand Down Expand Up @@ -142,6 +143,12 @@ class LIPSTICK_EXPORT LipstickNotification : public QObject
//! Nemo hint: play vibra feedback
static const char *HINT_VIBRA;

enum PresentationStyle {
DefaultNotificationStyle, // has summary and body, and possibly actions
MinimalStyle // has summary only, and no actions
};
Q_ENUM(PresentationStyle)

/*!
* Creates an object for storing information about a single notification.
*
Expand Down Expand Up @@ -270,6 +277,8 @@ class LIPSTICK_EXPORT LipstickNotification : public QObject

bool hasProgress() const;

PresentationStyle presentationStyle() const;

//! \internal
quint64 internalTimestamp() const;

Expand Down Expand Up @@ -342,6 +351,9 @@ class LIPSTICK_EXPORT LipstickNotification : public QObject
void hasProgressChanged();
void progressChanged();

//! Sent when the presentation style has been modified
void presentationStyleChanged();

private:
void updateHintValues();

Expand Down
54 changes: 35 additions & 19 deletions src/notifications/notificationpreviewpresenter.cpp
Expand Up @@ -94,22 +94,9 @@ void NotificationPreviewPresenter::showNextNotification()
} else {
LipstickNotification *notification = m_notificationQueue.takeFirst();

const bool screenLocked = m_screenLock->isScreenLocked() && m_screenLock->displayState() == TouchScreen::DisplayOff;
const bool deviceLocked = m_deviceLock->state() >= NemoDeviceLock::DeviceLock::Locked;
const bool notificationIsCritical = notification->urgency() >= 2 || notification->hints().value(LipstickNotification::HINT_DISPLAY_ON).toBool();

bool show = true;
if (deviceLocked) {
if (!notificationIsCritical) {
show = false;
} else {
show = m_deviceLock->showNotifications();
}
} else if (screenLocked) {
if (!notificationIsCritical) {
show = false;
}
}
// This is checked before queueing the notification but check again because e.g. the device
// lock state might have changed.
bool show = notificationShouldBeShown(notification);

if (!show) {
if (m_deviceLock->state() != NemoDeviceLock::DeviceLock::ManagerLockout) { // Suppress feedback if locked out.
Expand Down Expand Up @@ -208,18 +195,47 @@ bool NotificationPreviewPresenter::notificationShouldBeShown(LipstickNotificatio
return false; // would show up constantly as preview
}

const bool screenLocked = m_screenLock->isScreenLocked();
// We use two different presentation styles: one that can be clicked and one that cannot.
// Check for configurations that can't be correctly activated.
if (notification->remoteActions().count() == 0) {
if (!notification->previewSummary().isEmpty() && !notification->previewBody().isEmpty()) {
// Notifications with preview summary + preview body should have actions, as tapping on the preview pop-up should trigger some action
qWarning() << "Notification has both preview summary and preview body but no actions. Remove the preview body or add an action:"
<< notification->appName() << notification->category() << notification->previewSummary() << notification->previewBody();
}
} else {
if (!notification->previewSummary().isEmpty() && notification->previewBody().isEmpty()) {
// Notifications with preview summary but no body should not have any actions, as the small preview banner is too small to receive presses
qWarning() << "Warning: Notification has an action but only shows a preview summary. Add a preview body or remove the actions:"
<< notification->appName() << notification->category() << notification->previewSummary() << notification->previewBody();
} else if ((notification->previewSummary().isEmpty() && notification->previewBody().isEmpty()) && notification->hints().value("transient").toBool()) {
qWarning() << "Warning: Notification has actions but is transient and without a preview, its actions will not be triggerable from the UI:"
<< notification->appName() << notification->category() << notification->previewSummary() << notification->previewBody();
}
}

const bool screenLocked = m_screenLock->isScreenLocked() && m_screenLock->displayState() == TouchScreen::DisplayOff;
const bool deviceLocked = m_deviceLock->state() >= NemoDeviceLock::DeviceLock::Locked;
const bool notificationIsCritical = notification->urgency() >= 2 || notification->hints().value(LipstickNotification::HINT_DISPLAY_ON).toBool();
const bool showNotificationWhileDeviceLocked = notification->presentationStyle() == LipstickNotification::MinimalStyle || m_deviceLock->showNotifications();

if (deviceLocked
&& !notificationIsCritical
&& !showNotificationWhileDeviceLocked) {
return false;
}

if (screenLocked && !notificationIsCritical) {
return false;
}

uint mode = AllNotificationsEnabled;
QWaylandSurface *surface = LipstickCompositor::instance()->surfaceForId(LipstickCompositor::instance()->topmostWindowId());
if (surface != 0) {
mode = surface->windowProperties().value("NOTIFICATION_PREVIEWS_DISABLED", uint(AllNotificationsEnabled)).toUInt();
}

return ((!screenLocked && !deviceLocked) || notificationIsCritical) &&
(mode == AllNotificationsEnabled ||
return (mode == AllNotificationsEnabled ||
(mode == ApplicationNotificationsDisabled && notificationIsCritical) ||
(mode == SystemNotificationsDisabled && !notificationIsCritical));
}
Expand Down

0 comments on commit 95b5f40

Please sign in to comment.