mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-04-03 20:32:07 -04:00
replace qmlformat with a better tool
still not perfect, but well - what can ya do
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -9,186 +9,183 @@ import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
PanelWindow {
|
||||
id: root
|
||||
id: root
|
||||
|
||||
property bool notificationHistoryVisible: false
|
||||
property real triggerX: Screen.width - 400 - Theme.spacingL
|
||||
property real triggerY: Theme.barHeight + Theme.spacingXS
|
||||
property real triggerWidth: 40
|
||||
property string triggerSection: "right"
|
||||
property bool notificationHistoryVisible: false
|
||||
property real triggerX: Screen.width - 400 - Theme.spacingL
|
||||
property real triggerY: Theme.barHeight + Theme.spacingXS
|
||||
property real triggerWidth: 40
|
||||
property string triggerSection: "right"
|
||||
|
||||
function setTriggerPosition(x, y, width, section) {
|
||||
triggerX = x;
|
||||
triggerY = y;
|
||||
triggerWidth = width;
|
||||
triggerSection = section;
|
||||
function setTriggerPosition(x, y, width, section) {
|
||||
triggerX = x
|
||||
triggerY = y
|
||||
triggerWidth = width
|
||||
triggerSection = section
|
||||
}
|
||||
|
||||
visible: notificationHistoryVisible
|
||||
onNotificationHistoryVisibleChanged: {
|
||||
NotificationService.disablePopups(notificationHistoryVisible)
|
||||
}
|
||||
implicitWidth: 400
|
||||
implicitHeight: Math.min(Screen.height * 0.8, 400)
|
||||
WlrLayershell.layer: WlrLayershell.Overlay
|
||||
WlrLayershell.exclusiveZone: -1
|
||||
WlrLayershell.keyboardFocus: notificationHistoryVisible ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None
|
||||
color: "transparent"
|
||||
|
||||
anchors {
|
||||
top: true
|
||||
left: true
|
||||
right: true
|
||||
bottom: true
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
notificationHistoryVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: mainRect
|
||||
|
||||
function calculateHeight() {
|
||||
let baseHeight = Theme.spacingL * 2
|
||||
baseHeight += notificationHeader.height
|
||||
baseHeight += Theme.spacingM
|
||||
let listHeight = notificationList.listContentHeight
|
||||
if (NotificationService.groupedNotifications.length === 0)
|
||||
listHeight = 200
|
||||
|
||||
baseHeight += Math.min(listHeight, 600)
|
||||
return Math.max(300, baseHeight)
|
||||
}
|
||||
|
||||
visible: notificationHistoryVisible
|
||||
onNotificationHistoryVisibleChanged: {
|
||||
NotificationService.disablePopups(notificationHistoryVisible);
|
||||
}
|
||||
implicitWidth: 400
|
||||
implicitHeight: Math.min(Screen.height * 0.8, 400)
|
||||
WlrLayershell.layer: WlrLayershell.Overlay
|
||||
WlrLayershell.exclusiveZone: -1
|
||||
WlrLayershell.keyboardFocus: notificationHistoryVisible ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None
|
||||
color: "transparent"
|
||||
readonly property real popupWidth: 400
|
||||
readonly property real calculatedX: {
|
||||
var centerX = root.triggerX + (root.triggerWidth / 2) - (popupWidth / 2)
|
||||
|
||||
anchors {
|
||||
top: true
|
||||
left: true
|
||||
right: true
|
||||
bottom: true
|
||||
if (centerX >= Theme.spacingM
|
||||
&& centerX + popupWidth <= Screen.width - Theme.spacingM) {
|
||||
return centerX
|
||||
}
|
||||
|
||||
if (centerX < Theme.spacingM) {
|
||||
return Theme.spacingM
|
||||
}
|
||||
|
||||
if (centerX + popupWidth > Screen.width - Theme.spacingM) {
|
||||
return Screen.width - popupWidth - Theme.spacingM
|
||||
}
|
||||
|
||||
return centerX
|
||||
}
|
||||
|
||||
width: popupWidth
|
||||
height: calculateHeight()
|
||||
x: calculatedX
|
||||
y: root.triggerY
|
||||
color: Theme.popupBackground()
|
||||
radius: Theme.cornerRadiusLarge
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
|
||||
Theme.outline.b, 0.08)
|
||||
border.width: 1
|
||||
opacity: notificationHistoryVisible ? 1 : 0
|
||||
scale: notificationHistoryVisible ? 1 : 0.9
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
notificationHistoryVisible = false;
|
||||
}
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: mainRect
|
||||
Column {
|
||||
id: contentColumn
|
||||
|
||||
function calculateHeight() {
|
||||
let baseHeight = Theme.spacingL * 2;
|
||||
baseHeight += notificationHeader.height;
|
||||
baseHeight += Theme.spacingM;
|
||||
let listHeight = notificationList.listContentHeight;
|
||||
if (NotificationService.groupedNotifications.length === 0)
|
||||
listHeight = 200;
|
||||
|
||||
baseHeight += Math.min(listHeight, 600);
|
||||
return Math.max(300, baseHeight);
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
focus: true
|
||||
Component.onCompleted: {
|
||||
if (notificationHistoryVisible)
|
||||
forceActiveFocus()
|
||||
}
|
||||
Keys.onPressed: function (event) {
|
||||
if (event.key === Qt.Key_Escape) {
|
||||
notificationHistoryVisible = false
|
||||
event.accepted = true
|
||||
}
|
||||
}
|
||||
|
||||
readonly property real popupWidth: 400
|
||||
readonly property real calculatedX: {
|
||||
var centerX = root.triggerX + (root.triggerWidth / 2) - (popupWidth / 2);
|
||||
|
||||
if (centerX >= Theme.spacingM && centerX + popupWidth <= Screen.width - Theme.spacingM) {
|
||||
return centerX;
|
||||
}
|
||||
|
||||
if (centerX < Theme.spacingM) {
|
||||
return Theme.spacingM;
|
||||
}
|
||||
|
||||
if (centerX + popupWidth > Screen.width - Theme.spacingM) {
|
||||
return Screen.width - popupWidth - Theme.spacingM;
|
||||
}
|
||||
|
||||
return centerX;
|
||||
Connections {
|
||||
function onNotificationHistoryVisibleChanged() {
|
||||
if (notificationHistoryVisible)
|
||||
Qt.callLater(function () {
|
||||
contentColumn.forceActiveFocus()
|
||||
})
|
||||
else
|
||||
contentColumn.focus = false
|
||||
}
|
||||
target: root
|
||||
}
|
||||
|
||||
width: popupWidth
|
||||
height: calculateHeight()
|
||||
x: calculatedX
|
||||
y: root.triggerY
|
||||
color: Theme.popupBackground()
|
||||
radius: Theme.cornerRadiusLarge
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||
border.width: 1
|
||||
opacity: notificationHistoryVisible ? 1 : 0
|
||||
scale: notificationHistoryVisible ? 1 : 0.9
|
||||
NotificationHeader {
|
||||
id: notificationHeader
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: contentColumn
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
focus: true
|
||||
Component.onCompleted: {
|
||||
if (notificationHistoryVisible)
|
||||
forceActiveFocus();
|
||||
}
|
||||
Keys.onPressed: function(event) {
|
||||
if (event.key === Qt.Key_Escape) {
|
||||
notificationHistoryVisible = false;
|
||||
event.accepted = true;
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
function onNotificationHistoryVisibleChanged() {
|
||||
if (notificationHistoryVisible)
|
||||
Qt.callLater(function() {
|
||||
contentColumn.forceActiveFocus();
|
||||
});
|
||||
else
|
||||
contentColumn.focus = false;
|
||||
}
|
||||
target: root
|
||||
}
|
||||
|
||||
NotificationHeader {
|
||||
id: notificationHeader
|
||||
}
|
||||
|
||||
NotificationList {
|
||||
id: notificationList
|
||||
|
||||
width: parent.width
|
||||
height: parent.height - notificationHeader.height - contentColumn.spacing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Connections {
|
||||
function onNotificationsChanged() {
|
||||
mainRect.height = mainRect.calculateHeight();
|
||||
}
|
||||
|
||||
function onGroupedNotificationsChanged() {
|
||||
mainRect.height = mainRect.calculateHeight();
|
||||
}
|
||||
|
||||
function onExpandedGroupsChanged() {
|
||||
mainRect.height = mainRect.calculateHeight();
|
||||
}
|
||||
|
||||
function onExpandedMessagesChanged() {
|
||||
mainRect.height = mainRect.calculateHeight();
|
||||
}
|
||||
|
||||
target: NotificationService
|
||||
}
|
||||
|
||||
Behavior on height {
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Anims.durMed
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Anims.emphasized
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Behavior on scale {
|
||||
NumberAnimation {
|
||||
duration: Anims.durMed
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Anims.emphasized
|
||||
}
|
||||
|
||||
}
|
||||
NotificationList {
|
||||
id: notificationList
|
||||
|
||||
width: parent.width
|
||||
height: parent.height - notificationHeader.height - contentColumn.spacing
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
function onNotificationsChanged() {
|
||||
mainRect.height = mainRect.calculateHeight()
|
||||
}
|
||||
|
||||
function onGroupedNotificationsChanged() {
|
||||
mainRect.height = mainRect.calculateHeight()
|
||||
}
|
||||
|
||||
function onExpandedGroupsChanged() {
|
||||
mainRect.height = mainRect.calculateHeight()
|
||||
}
|
||||
|
||||
function onExpandedMessagesChanged() {
|
||||
mainRect.height = mainRect.calculateHeight()
|
||||
}
|
||||
|
||||
target: NotificationService
|
||||
}
|
||||
|
||||
Behavior on height {
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Anims.durMed
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Anims.emphasized
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on scale {
|
||||
NumberAnimation {
|
||||
duration: Anims.durMed
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Anims.emphasized
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,33 +4,33 @@ import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Item {
|
||||
id: root
|
||||
id: root
|
||||
|
||||
width: parent.width
|
||||
height: 200
|
||||
visible: NotificationService.notifications.length === 0
|
||||
width: parent.width
|
||||
height: 200
|
||||
visible: NotificationService.notifications.length === 0
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingXS
|
||||
width: parent.width * 0.8
|
||||
|
||||
DankIcon {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
name: "notifications_none"
|
||||
size: Theme.iconSizeLarge + 16
|
||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.3)
|
||||
}
|
||||
|
||||
StyledText {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: "Nothing to see here"
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.3)
|
||||
font.weight: Font.Medium
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingXS
|
||||
width: parent.width * 0.8
|
||||
|
||||
DankIcon {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
name: "notifications_none"
|
||||
size: Theme.iconSizeLarge + 16
|
||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
|
||||
Theme.surfaceText.b, 0.3)
|
||||
}
|
||||
|
||||
StyledText {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: "Nothing to see here"
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
|
||||
Theme.surfaceText.b, 0.3)
|
||||
font.weight: Font.Medium
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,132 +5,129 @@ import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Item {
|
||||
id: root
|
||||
id: root
|
||||
|
||||
width: parent.width
|
||||
height: 32
|
||||
width: parent.width
|
||||
height: 32
|
||||
|
||||
Row {
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: Theme.spacingXS
|
||||
Row {
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
StyledText {
|
||||
text: "Notifications"
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
DankActionButton {
|
||||
id: doNotDisturbButton
|
||||
|
||||
iconName: SessionData.doNotDisturb ? "notifications_off" : "notifications"
|
||||
iconColor: SessionData.doNotDisturb ? Theme.error : Theme.surfaceText
|
||||
buttonSize: 28
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
onClicked: SessionData.setDoNotDisturb(!SessionData.doNotDisturb)
|
||||
|
||||
Rectangle {
|
||||
id: doNotDisturbTooltip
|
||||
|
||||
width: tooltipText.contentWidth + Theme.spacingS * 2
|
||||
height: tooltipText.contentHeight + Theme.spacingXS * 2
|
||||
radius: Theme.cornerRadiusSmall
|
||||
color: Theme.surfaceContainer
|
||||
border.color: Theme.outline
|
||||
border.width: 1
|
||||
anchors.bottom: parent.top
|
||||
anchors.bottomMargin: Theme.spacingS
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
visible: doNotDisturbButton.children[1].containsMouse // Access StateLayer's containsMouse
|
||||
opacity: visible ? 1 : 0
|
||||
|
||||
StyledText {
|
||||
text: "Notifications"
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
id: tooltipText
|
||||
|
||||
text: "Do Not Disturb"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
anchors.centerIn: parent
|
||||
font.hintingPreference: Font.PreferFullHinting
|
||||
}
|
||||
|
||||
DankActionButton {
|
||||
id: doNotDisturbButton
|
||||
|
||||
iconName: SessionData.doNotDisturb ? "notifications_off" : "notifications"
|
||||
iconColor: SessionData.doNotDisturb ? Theme.error : Theme.surfaceText
|
||||
buttonSize: 28
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
onClicked: SessionData.setDoNotDisturb(!SessionData.doNotDisturb)
|
||||
|
||||
Rectangle {
|
||||
id: doNotDisturbTooltip
|
||||
|
||||
width: tooltipText.contentWidth + Theme.spacingS * 2
|
||||
height: tooltipText.contentHeight + Theme.spacingXS * 2
|
||||
radius: Theme.cornerRadiusSmall
|
||||
color: Theme.surfaceContainer
|
||||
border.color: Theme.outline
|
||||
border.width: 1
|
||||
anchors.bottom: parent.top
|
||||
anchors.bottomMargin: Theme.spacingS
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
visible: doNotDisturbButton.children[1].containsMouse // Access StateLayer's containsMouse
|
||||
opacity: visible ? 1 : 0
|
||||
|
||||
StyledText {
|
||||
id: tooltipText
|
||||
|
||||
text: "Do Not Disturb"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
anchors.centerIn: parent
|
||||
font.hintingPreference: Font.PreferFullHinting
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: clearAllButton
|
||||
Rectangle {
|
||||
id: clearAllButton
|
||||
|
||||
width: 120
|
||||
height: 28
|
||||
radius: Theme.cornerRadiusLarge
|
||||
anchors.right: parent.right
|
||||
width: 120
|
||||
height: 28
|
||||
radius: Theme.cornerRadiusLarge
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: NotificationService.notifications.length > 0
|
||||
color: clearArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g,
|
||||
Theme.primary.b, 0.12) : Qt.rgba(
|
||||
Theme.surfaceVariant.r,
|
||||
Theme.surfaceVariant.g,
|
||||
Theme.surfaceVariant.b, 0.3)
|
||||
border.color: clearArea.containsMouse ? Theme.primary : Qt.rgba(
|
||||
Theme.outline.r, Theme.outline.g,
|
||||
Theme.outline.b, 0.08)
|
||||
border.width: 1
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
DankIcon {
|
||||
name: "delete_sweep"
|
||||
size: Theme.iconSizeSmall
|
||||
color: clearArea.containsMouse ? Theme.primary : Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: NotificationService.notifications.length > 0
|
||||
color: clearArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
|
||||
border.color: clearArea.containsMouse ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||
border.width: 1
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
DankIcon {
|
||||
name: "delete_sweep"
|
||||
size: Theme.iconSizeSmall
|
||||
color: clearArea.containsMouse ? Theme.primary : Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "Clear All"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: clearArea.containsMouse ? Theme.primary : Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: clearArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: NotificationService.clearAllNotifications()
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Behavior on border.color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "Clear All"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: clearArea.containsMouse ? Theme.primary : Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: clearArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: NotificationService.clearAllNotifications()
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on border.color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,24 +5,23 @@ import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
DankListView {
|
||||
id: root
|
||||
id: root
|
||||
|
||||
property alias count: root.count
|
||||
property alias listContentHeight: root.contentHeight
|
||||
property alias count: root.count
|
||||
property alias listContentHeight: root.contentHeight
|
||||
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
clip: true
|
||||
model: NotificationService.groupedNotifications
|
||||
spacing: Theme.spacingL
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
clip: true
|
||||
model: NotificationService.groupedNotifications
|
||||
spacing: Theme.spacingL
|
||||
|
||||
NotificationEmptyState {
|
||||
visible: root.count === 0
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
NotificationEmptyState {
|
||||
visible: root.count === 0
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
|
||||
delegate: NotificationCard {
|
||||
notificationGroup: modelData
|
||||
}
|
||||
delegate: NotificationCard {
|
||||
notificationGroup: modelData
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,242 +4,246 @@ import qs.Common
|
||||
import qs.Services
|
||||
|
||||
QtObject {
|
||||
id: manager
|
||||
id: manager
|
||||
|
||||
property var modelData
|
||||
property int topMargin: 0
|
||||
property int baseNotificationHeight: 120
|
||||
property int maxTargetNotifications: 3
|
||||
property var popupWindows: [] // strong refs to windows (live until exitFinished)
|
||||
property var destroyingWindows: new Set()
|
||||
property Component popupComponent
|
||||
property var modelData
|
||||
property int topMargin: 0
|
||||
property int baseNotificationHeight: 120
|
||||
property int maxTargetNotifications: 3
|
||||
property var popupWindows: [] // strong refs to windows (live until exitFinished)
|
||||
property var destroyingWindows: new Set()
|
||||
property Component popupComponent
|
||||
|
||||
popupComponent: Component {
|
||||
NotificationPopup {
|
||||
onEntered: manager._onPopupEntered(this)
|
||||
onExitFinished: manager._onPopupExitFinished(this)
|
||||
}
|
||||
popupComponent: Component {
|
||||
NotificationPopup {
|
||||
onEntered: manager._onPopupEntered(this)
|
||||
onExitFinished: manager._onPopupExitFinished(this)
|
||||
}
|
||||
}
|
||||
|
||||
property Connections notificationConnections
|
||||
|
||||
notificationConnections: Connections {
|
||||
function onVisibleNotificationsChanged() {
|
||||
manager._sync(NotificationService.visibleNotifications)
|
||||
}
|
||||
|
||||
property Connections notificationConnections
|
||||
target: NotificationService
|
||||
}
|
||||
|
||||
notificationConnections: Connections {
|
||||
function onVisibleNotificationsChanged() {
|
||||
manager._sync(NotificationService.visibleNotifications);
|
||||
property Timer sweeper
|
||||
|
||||
sweeper: Timer {
|
||||
interval: 2000
|
||||
running: false // Not running by default
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
let toRemove = []
|
||||
for (let p of popupWindows) {
|
||||
if (!p) {
|
||||
toRemove.push(p)
|
||||
continue
|
||||
}
|
||||
const isZombie = p.status === Component.Null || (!p.visible
|
||||
&& !p.exiting)
|
||||
|| (!p.notificationData && !p._isDestroying)
|
||||
|| (!p.hasValidData && !p._isDestroying)
|
||||
if (isZombie) {
|
||||
|
||||
target: NotificationService
|
||||
}
|
||||
toRemove.push(p)
|
||||
if (p.forceExit) {
|
||||
p.forceExit()
|
||||
} else if (p.destroy) {
|
||||
try {
|
||||
p.destroy()
|
||||
} catch (e) {
|
||||
|
||||
property Timer sweeper
|
||||
|
||||
sweeper: Timer {
|
||||
interval: 2000
|
||||
running: false // Not running by default
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
let toRemove = [];
|
||||
for (let p of popupWindows) {
|
||||
if (!p) {
|
||||
toRemove.push(p);
|
||||
continue;
|
||||
}
|
||||
const isZombie = p.status === Component.Null || (!p.visible && !p.exiting) || (!p.notificationData && !p._isDestroying) || (!p.hasValidData && !p._isDestroying);
|
||||
if (isZombie) {
|
||||
|
||||
toRemove.push(p);
|
||||
if (p.forceExit) {
|
||||
p.forceExit();
|
||||
} else if (p.destroy) {
|
||||
try {
|
||||
p.destroy();
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (toRemove.length > 0) {
|
||||
for (let zombie of toRemove) {
|
||||
const i = popupWindows.indexOf(zombie);
|
||||
if (i !== -1)
|
||||
popupWindows.splice(i, 1);
|
||||
|
||||
}
|
||||
popupWindows = popupWindows.slice();
|
||||
const survivors = _active().sort((a, b) => {
|
||||
return a.screenY - b.screenY;
|
||||
});
|
||||
for (let k = 0; k < survivors.length; ++k) {
|
||||
survivors[k].screenY = topMargin + k * baseNotificationHeight;
|
||||
}
|
||||
}
|
||||
if (popupWindows.length === 0)
|
||||
sweeper.stop();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _hasWindowFor(w) {
|
||||
return popupWindows.some((p) => {
|
||||
return p && p.notificationData === w && !p._isDestroying && p.status !== Component.Null;
|
||||
});
|
||||
}
|
||||
|
||||
function _isValidWindow(p) {
|
||||
return p && p.status !== Component.Null && !p._isDestroying && p.hasValidData;
|
||||
}
|
||||
|
||||
function _sync(newWrappers) {
|
||||
for (let w of newWrappers) {
|
||||
if (w && !_hasWindowFor(w))
|
||||
insertNewestAtTop(w);
|
||||
|
||||
}
|
||||
if (toRemove.length > 0) {
|
||||
for (let zombie of toRemove) {
|
||||
const i = popupWindows.indexOf(zombie)
|
||||
if (i !== -1)
|
||||
popupWindows.splice(i, 1)
|
||||
}
|
||||
for (let p of popupWindows.slice()) {
|
||||
if (!_isValidWindow(p))
|
||||
continue;
|
||||
|
||||
if (p.notificationData && newWrappers.indexOf(p.notificationData) === -1 && !p.exiting) {
|
||||
p.notificationData.removedByLimit = true;
|
||||
p.notificationData.popup = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function insertNewestAtTop(wrapper) {
|
||||
if (!wrapper) {
|
||||
|
||||
return ;
|
||||
}
|
||||
for (let p of popupWindows) {
|
||||
if (!_isValidWindow(p))
|
||||
continue;
|
||||
|
||||
if (p.exiting)
|
||||
continue;
|
||||
|
||||
p.screenY = p.screenY + baseNotificationHeight;
|
||||
}
|
||||
const notificationId = wrapper && wrapper.notification ? wrapper.notification.id : "";
|
||||
const win = popupComponent.createObject(null, {
|
||||
"notificationData": wrapper,
|
||||
"notificationId": notificationId,
|
||||
"screenY": topMargin,
|
||||
"screen": manager.modelData
|
||||
});
|
||||
if (!win) {
|
||||
|
||||
return ;
|
||||
}
|
||||
if (!win.hasValidData) {
|
||||
|
||||
win.destroy();
|
||||
return ;
|
||||
}
|
||||
popupWindows.push(win);
|
||||
if (!sweeper.running)
|
||||
sweeper.start();
|
||||
|
||||
_maybeStartOverflow();
|
||||
}
|
||||
|
||||
function _active() {
|
||||
return popupWindows.filter((p) => {
|
||||
return _isValidWindow(p) && p.notificationData && p.notificationData.popup && !p.exiting;
|
||||
});
|
||||
}
|
||||
|
||||
function _bottom() {
|
||||
let b = null, maxY = -1;
|
||||
for (let p of _active()) {
|
||||
if (p.screenY > maxY) {
|
||||
maxY = p.screenY;
|
||||
b = p;
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
function _maybeStartOverflow() {
|
||||
const activeWindows = _active();
|
||||
if (activeWindows.length <= maxTargetNotifications + 1)
|
||||
return ;
|
||||
|
||||
const b = _bottom();
|
||||
if (b && !b.exiting) {
|
||||
b.notificationData.removedByLimit = true;
|
||||
b.notificationData.popup = false;
|
||||
}
|
||||
}
|
||||
|
||||
function _onPopupEntered(p) {
|
||||
if (_isValidWindow(p))
|
||||
_maybeStartOverflow();
|
||||
|
||||
}
|
||||
|
||||
function _onPopupExitFinished(p) {
|
||||
if (!p)
|
||||
return ;
|
||||
|
||||
const windowId = p.toString();
|
||||
if (destroyingWindows.has(windowId))
|
||||
return ;
|
||||
|
||||
destroyingWindows.add(windowId);
|
||||
const i = popupWindows.indexOf(p);
|
||||
if (i !== -1) {
|
||||
popupWindows.splice(i, 1);
|
||||
popupWindows = popupWindows.slice();
|
||||
}
|
||||
if (NotificationService.releaseWrapper && p.notificationData)
|
||||
NotificationService.releaseWrapper(p.notificationData);
|
||||
|
||||
Qt.callLater(() => {
|
||||
if (p && p.destroy) {
|
||||
try {
|
||||
p.destroy();
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
}
|
||||
Qt.callLater(() => {
|
||||
destroyingWindows.delete(windowId);
|
||||
});
|
||||
});
|
||||
popupWindows = popupWindows.slice()
|
||||
const survivors = _active().sort((a, b) => {
|
||||
return a.screenY - b.screenY;
|
||||
});
|
||||
for (let k = 0; k < survivors.length; ++k) {
|
||||
survivors[k].screenY = topMargin + k * baseNotificationHeight;
|
||||
return a.screenY - b.screenY
|
||||
})
|
||||
for (var k = 0; k < survivors.length; ++k) {
|
||||
survivors[k].screenY = topMargin + k * baseNotificationHeight
|
||||
}
|
||||
_maybeStartOverflow();
|
||||
}
|
||||
if (popupWindows.length === 0)
|
||||
sweeper.stop()
|
||||
}
|
||||
}
|
||||
|
||||
function _hasWindowFor(w) {
|
||||
return popupWindows.some(p => {
|
||||
return p && p.notificationData === w
|
||||
&& !p._isDestroying
|
||||
&& p.status !== Component.Null
|
||||
})
|
||||
}
|
||||
|
||||
function _isValidWindow(p) {
|
||||
return p && p.status !== Component.Null && !p._isDestroying
|
||||
&& p.hasValidData
|
||||
}
|
||||
|
||||
function _sync(newWrappers) {
|
||||
for (let w of newWrappers) {
|
||||
if (w && !_hasWindowFor(w))
|
||||
insertNewestAtTop(w)
|
||||
}
|
||||
for (let p of popupWindows.slice()) {
|
||||
if (!_isValidWindow(p))
|
||||
continue
|
||||
|
||||
if (p.notificationData && newWrappers.indexOf(p.notificationData) === -1
|
||||
&& !p.exiting) {
|
||||
p.notificationData.removedByLimit = true
|
||||
p.notificationData.popup = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function insertNewestAtTop(wrapper) {
|
||||
if (!wrapper) {
|
||||
|
||||
return
|
||||
}
|
||||
for (let p of popupWindows) {
|
||||
if (!_isValidWindow(p))
|
||||
continue
|
||||
|
||||
if (p.exiting)
|
||||
continue
|
||||
|
||||
p.screenY = p.screenY + baseNotificationHeight
|
||||
}
|
||||
const notificationId = wrapper
|
||||
&& wrapper.notification ? wrapper.notification.id : ""
|
||||
const win = popupComponent.createObject(null, {
|
||||
"notificationData": wrapper,
|
||||
"notificationId": notificationId,
|
||||
"screenY": topMargin,
|
||||
"screen": manager.modelData
|
||||
})
|
||||
if (!win) {
|
||||
|
||||
return
|
||||
}
|
||||
if (!win.hasValidData) {
|
||||
|
||||
win.destroy()
|
||||
return
|
||||
}
|
||||
popupWindows.push(win)
|
||||
if (!sweeper.running)
|
||||
sweeper.start()
|
||||
|
||||
_maybeStartOverflow()
|
||||
}
|
||||
|
||||
function _active() {
|
||||
return popupWindows.filter(p => {
|
||||
return _isValidWindow(p) && p.notificationData
|
||||
&& p.notificationData.popup && !p.exiting
|
||||
})
|
||||
}
|
||||
|
||||
function _bottom() {
|
||||
let b = null, maxY = -1
|
||||
for (let p of _active()) {
|
||||
if (p.screenY > maxY) {
|
||||
maxY = p.screenY
|
||||
b = p
|
||||
}
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
function _maybeStartOverflow() {
|
||||
const activeWindows = _active()
|
||||
if (activeWindows.length <= maxTargetNotifications + 1)
|
||||
return
|
||||
|
||||
const b = _bottom()
|
||||
if (b && !b.exiting) {
|
||||
b.notificationData.removedByLimit = true
|
||||
b.notificationData.popup = false
|
||||
}
|
||||
}
|
||||
|
||||
function _onPopupEntered(p) {
|
||||
if (_isValidWindow(p))
|
||||
_maybeStartOverflow()
|
||||
}
|
||||
|
||||
function _onPopupExitFinished(p) {
|
||||
if (!p)
|
||||
return
|
||||
|
||||
const windowId = p.toString()
|
||||
if (destroyingWindows.has(windowId))
|
||||
return
|
||||
|
||||
destroyingWindows.add(windowId)
|
||||
const i = popupWindows.indexOf(p)
|
||||
if (i !== -1) {
|
||||
popupWindows.splice(i, 1)
|
||||
popupWindows = popupWindows.slice()
|
||||
}
|
||||
if (NotificationService.releaseWrapper && p.notificationData)
|
||||
NotificationService.releaseWrapper(p.notificationData)
|
||||
|
||||
Qt.callLater(() => {
|
||||
if (p && p.destroy) {
|
||||
try {
|
||||
p.destroy()
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
}
|
||||
Qt.callLater(() => {
|
||||
destroyingWindows.delete(windowId)
|
||||
})
|
||||
})
|
||||
const survivors = _active().sort((a, b) => {
|
||||
return a.screenY - b.screenY
|
||||
})
|
||||
for (var k = 0; k < survivors.length; ++k) {
|
||||
survivors[k].screenY = topMargin + k * baseNotificationHeight
|
||||
}
|
||||
_maybeStartOverflow()
|
||||
}
|
||||
|
||||
function cleanupAllWindows() {
|
||||
sweeper.stop()
|
||||
for (let p of popupWindows.slice()) {
|
||||
if (p) {
|
||||
try {
|
||||
if (p.forceExit)
|
||||
p.forceExit()
|
||||
else if (p.destroy)
|
||||
p.destroy()
|
||||
} catch (e) {
|
||||
|
||||
function cleanupAllWindows() {
|
||||
sweeper.stop();
|
||||
for (let p of popupWindows.slice()) {
|
||||
if (p) {
|
||||
try {
|
||||
if (p.forceExit)
|
||||
p.forceExit();
|
||||
else if (p.destroy)
|
||||
p.destroy();
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
popupWindows = [];
|
||||
destroyingWindows.clear();
|
||||
}
|
||||
}
|
||||
popupWindows = []
|
||||
destroyingWindows.clear()
|
||||
}
|
||||
|
||||
onPopupWindowsChanged: {
|
||||
if (popupWindows.length > 0 && !sweeper.running)
|
||||
sweeper.start();
|
||||
else if (popupWindows.length === 0 && sweeper.running)
|
||||
sweeper.stop();
|
||||
}
|
||||
onPopupWindowsChanged: {
|
||||
if (popupWindows.length > 0 && !sweeper.running)
|
||||
sweeper.start()
|
||||
else if (popupWindows.length === 0 && sweeper.running)
|
||||
sweeper.stop()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user