Commit d8399e88 authored by Yari Polla's avatar Yari Polla Committed by Devin Lin
Browse files

toppanel/notifications: add clean all and do not disturb

Hi, this MR adds "clear all" and "do not disturb" buttons to `NotificationsWidget`.

Few other corrections have been made:
 - Transitions should now work correctly, plus they can be disabled via `MobileShell.MobileShellSettings.animationsEnabled`;
 - Loaders are now asynchronous;
 - List items have now their own margins, in order to not clip their shadows.\

It only remains to implement a context menu to set do not disturb mode for a given period of time. I think it's a secondary feature on which we can work later, but in case tell me what to do.

Unfortunately I can't test the lockscreen on a phone at the moment, and I cannot take a performance test as well. It would be great if someone tested all these things, otherwise I'll provide as soon as possible.

Closes: #134
parent db86c142
Pipeline #195397 passed with stage
in 1 minute and 5 seconds
......@@ -71,6 +71,7 @@ PlasmaCore.ColorScope {
top: mediaWidget.bottom
topMargin: 0
bottom: parent.bottom
bottomMargin: 0
right: quickSettings.left
left: parent.left
}
......
......@@ -43,7 +43,7 @@ PlasmaCore.ColorScope {
color: Qt.rgba(PlasmaCore.Theme.backgroundColor.r,
PlasmaCore.Theme.backgroundColor.g,
PlasmaCore.Theme.backgroundColor.b,
notificationWidget.hasNotifications ? 0.95 : 0.7)
0.95)
Behavior on color { ColorAnimation { duration: PlasmaCore.Units.longDuration } }
opacity: Math.max(0, Math.min(1, actionDrawer.offset / root.minimizedQuickSettingsOffset))
}
......@@ -114,11 +114,8 @@ PlasmaCore.ColorScope {
top: quickSettings.top
topMargin: quickSettings.height + translate.y
bottom: parent.bottom
bottomMargin: PlasmaCore.Units.largeSpacing
left: parent.left
leftMargin: PlasmaCore.Units.largeSpacing
right: parent.right
rightMargin: PlasmaCore.Units.largeSpacing
}
opacity: applyMinMax(root.actionDrawer.offset / root.minimizedQuickSettingsOffset)
}
......
......@@ -6,7 +6,7 @@
*/
import QtQuick 2.15
import QtQuick.Layouts 1.1
import QtQuick.Layouts 1.15
import QtQuick.Window 2.2
import QtGraphicalEffects 1.12
......@@ -29,17 +29,17 @@ Item {
/**
* The notification model for the widget.
*/
property var historyModel: []
property var historyModel
/**
* The type of notification model used for the widget.
*/
property int historyModelType: NotificationsModelType.NotificationsModel
property int historyModelType
/**
* The notification model settings for the widget.
*/
property var notificationSettings: NotificationManager.Settings {}
property var notificationSettings
/**
* Whether invoking notification actions requires authentiation of some sort.
......@@ -55,6 +55,8 @@ Item {
*/
readonly property bool hasNotifications: list.count > 0
readonly property bool doNotDisturbModeEnabled: !isNaN(notificationSettings.notificationsInhibitedUntil)
enum ModelType {
NotificationsModel, // used in the logged-in shell
WatchedNotificationsModel // used on the lockscreen
......@@ -85,8 +87,29 @@ Item {
*/
function clearHistory() {
historyModel.clear(NotificationManager.Notifications.ClearExpired);
if (historyModel.count === 0) {
backgroundClicked();
}
}
/**
* Toggles Do Not Disturb mode.
*/
function toggleDoNotDisturbMode() {
if (doNotDisturbModeEnabled) {
notificationSettings.defaults();
} else {
var until = new Date();
until.setFullYear(until.getFullYear() + 1);
notificationSettings.notificationsInhibitedUntil = until;
}
notificationSettings.save();
}
/**
* Open the system notification settings.
*/
......@@ -102,34 +125,50 @@ Item {
intervalAlignment: PlasmaCore.Types.AlignToMinute
}
// implement background clicking signal
MouseArea {
anchors.fill: parent
onClicked: backgroundClicked()
z: -1 // ensure that this is below notification items so we don't steal button clicks
}
ListView {
id: list
model: historyModel
currentIndex: -1
clip: true
currentIndex: 0
property var pendingNotificationWithAction
readonly property int animationDuration: MobileShell.MobileShellSettings.animationsEnabled ? PlasmaCore.Units.longDuration : 0
// If a screen overflow occurs, fix height in order to maintain tool buttons in place.
readonly property bool listOverflowing: contentItem.childrenRect.height + toolButtons.height + bottomMargin + spacing >= root.height
bottomMargin: spacing * 2
height: count === 0 ? 0 : listOverflowing ? root.height - toolButtons.height - bottomMargin : contentItem.childrenRect.height + spacing
anchors {
top: parent.top
left: parent.left
right: parent.right
}
boundsBehavior: Flickable.StopAtBounds
spacing: Kirigami.Units.largeSpacing
anchors.fill: parent
// TODO keyboard focus
highlightMoveDuration: 0
highlightResizeDuration: 0
highlight: Item {}
section {
property: "isInGroup"
property: "isGroup"
criteria: ViewSection.FullString
}
// implement background clicking signal
MouseArea {
anchors.fill: parent
onClicked: root.backgroundClicked()
z: -1 // ensure that this is below notification items so we don't steal button clicks
}
PlasmaExtras.PlaceholderMessage {
anchors.centerIn: parent
......@@ -149,26 +188,15 @@ Item {
}
}
// Run every time an item is visually added to the list, thus when `Show n more` button is clicked as well.
add: Transition {
SequentialAnimation {
PropertyAction { property: "opacity"; value: 0 }
PauseAnimation { duration: PlasmaCore.Units.longDuration }
ParallelAnimation {
NumberAnimation { property: "opacity"; from: 0; to: 1; duration: PlasmaCore.Units.longDuration }
NumberAnimation { property: "height"; from: 0; duration: PlasmaCore.Units.longDuration }
}
}
NumberAnimation { property: "opacity"; from: 0; to: 1; duration: list.animationDuration }
}
addDisplaced: Transition {
NumberAnimation { properties: "y"; duration: PlasmaCore.Units.longDuration }
// Run every time an item is displaced, such as when the order is scrambled due to a group expansion.
displaced: Transition {
NumberAnimation { properties: "y"; duration: list.animationDuration }
}
removeDisplaced: Transition {
SequentialAnimation {
PauseAnimation { duration: PlasmaCore.Units.longDuration }
NumberAnimation { properties: "y"; duration: PlasmaCore.Units.longDuration }
}
}
function isRowExpanded(row) {
var idx = historyModel.index(row, 0);
return historyModel.data(idx, NotificationManager.Notifications.IsGroupExpandedRole);
......@@ -191,19 +219,38 @@ Item {
}
}
}
// Instantly re-align items after group expansion.
forceLayout();
}
delegate: Loader {
id: delegateLoader
width: list.width
anchors {
left: parent ? parent.left : undefined
leftMargin: PlasmaCore.Units.largeSpacing
right: parent ? parent.right : undefined
rightMargin: PlasmaCore.Units.largeSpacing
}
height: model.isGroup ? groupDelegate.height : notificationDelegate.height
sourceComponent: model.isGroup ? groupDelegate : notificationDelegate
asynchronous: true
required property var model
required property int index
// We have to do this here in order to control the animation before the item is completely removed
ListView.onRemove: SequentialAnimation {
PropertyAction { target: delegateLoader; property: "ListView.delayRemove"; value: true }
NumberAnimation { target: delegateLoader; property: "opacity"; to: 0.0; duration: list.animationDuration }
PropertyAction { target: delegateLoader; property: "ListView.delayRemove"; value: false }
}
Component {
id: groupDelegate
NotificationGroupHeader {
NotificationGroupHeader {
applicationName: model.applicationName
applicationIconSource: model.applicationIconName
originName: model.originName || ""
......@@ -213,12 +260,16 @@ Item {
Component {
id: notificationDelegate
ColumnLayout {
Column {
spacing: PlasmaCore.Units.smallSpacing
height: notificationItem.height + showMoreLoader.height
NotificationItem {
id: notificationItem
Layout.fillWidth: true
width: parent.width
height: implicitHeight
model: delegateLoader.model
modelIndex: delegateLoader.index
......@@ -233,16 +284,37 @@ Item {
}
}
// Every item has got an instance of this loader, but it becomes active only for last ones that take place in big enough groups.
Loader {
id: showMoreLoader
height: visible ? implicitHeight : 0
opacity: 0.0
visible: active
asynchronous: true
active: {
// if we have the WatchedNotificationsModel, we don't have notification grouping support
if (typeof model.groupChildrenCount === 'undefined')
return false;
return (model.groupChildrenCount > model.expandedGroupChildrenCount || model.isGroupExpanded)
&& delegateLoader.ListView.nextSection !== delegateLoader.ListView.section
&& delegateLoader.ListView.nextSection != delegateLoader.ListView.section;
}
// state + transition: animates the item when it becomes visible. Fade off is handled by above ListView.onRemove.
states: State {
name: "VISIBLE"
when: showMoreLoader.status == Loader.Ready
PropertyChanges { target: showMoreLoader; opacity: 1.0 }
}
transitions: Transition {
to: "VISIBLE"
SequentialAnimation {
PauseAnimation { duration: list.animationDuration * 2 }
NumberAnimation { properties: "opacity"; duration: list.animationDuration }
}
}
sourceComponent: PlasmaComponents3.ToolButton {
......@@ -250,11 +322,86 @@ Item {
text: model.isGroupExpanded ? i18n("Show Fewer")
: i18nc("Expand to show n more notifications",
"Show %1 More", (model.groupChildrenCount - model.expandedGroupChildrenCount))
onClicked: list.setGroupExpanded(model.index, !model.isGroupExpanded)
onClicked: {
list.setGroupExpanded(model.index, !model.isGroupExpanded)
}
}
}
}
}
}
}
Item {
id: toolButtons
visible: !root.actionsRequireUnlock
width: root.width
height: toolLayout.implicitHeight + spacer.height
anchors {
top: list.bottom
left: parent.left
right: parent.right
}
Rectangle {
id: spacer
visible: list.listOverflowing
anchors {
top: toolButtons.top
left: toolButtons.left
right: toolButtons.right
}
height: 1
opacity: 0.25
color: PlasmaCore.Theme.textColor
}
RowLayout {
id: toolLayout
anchors {
top: spacer.bottom
topMargin: list.spacing
left: parent.left
leftMargin: PlasmaCore.Units.smallSpacing
right: parent.right
rightMargin: PlasmaCore.Units.smallSpacing
bottom: parent.bottom
bottomMargin: list.spacing
}
PlasmaComponents3.ToolButton {
id: doNotDisturbButton
Layout.alignment: hasNotifications ? Qt.AlignLeft : Qt.AlignHCenter
font.bold: true
icon.name: doNotDisturbModeEnabled ? "notifications" : "notifications-disabled"
text: doNotDisturbModeEnabled ? "Enable Notifications" : "Do Not Disturb"
onClicked: toggleDoNotDisturbMode()
}
PlasmaComponents3.ToolButton {
id: clearButton
Layout.alignment: Qt.AlignRight
visible: hasNotifications
font.bold: true
icon.name: "edit-clear-history"
text: "Clear All Notifications"
onClicked: clearHistory()
}
}
}
}
......@@ -13,10 +13,13 @@ import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.notificationmanager 1.1 as Notifications
import org.kde.plasma.private.mobileshell 1.0 as MobileShell
import org.kde.notificationmanager 1.0 as NotificationManager
Rectangle {
id: root
required property var lockScreenState
property var notificationsModel: []
property var notificationSettings: NotificationManager.Settings {}
readonly property bool notificationsShown: notificationsList.hasNotifications
......@@ -61,6 +64,7 @@ Rectangle {
historyModelType: MobileShell.NotificationsModelType.WatchedNotificationsModel
actionsRequireUnlock: true
historyModel: root.notificationsModel
notificationSettings: root.notificationSettings
property bool requestNotificationAction: false
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment