mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-24 21:42:51 -05:00
notifications: add compact mode, expansion in history, expansion in
popup fixes #1282
This commit is contained in:
@@ -404,6 +404,7 @@ Singleton {
|
|||||||
property int notificationTimeoutLow: 5000
|
property int notificationTimeoutLow: 5000
|
||||||
property int notificationTimeoutNormal: 5000
|
property int notificationTimeoutNormal: 5000
|
||||||
property int notificationTimeoutCritical: 0
|
property int notificationTimeoutCritical: 0
|
||||||
|
property bool notificationCompactMode: false
|
||||||
property int notificationPopupPosition: SettingsData.Position.Top
|
property int notificationPopupPosition: SettingsData.Position.Top
|
||||||
property bool notificationHistoryEnabled: true
|
property bool notificationHistoryEnabled: true
|
||||||
property int notificationHistoryMaxCount: 50
|
property int notificationHistoryMaxCount: 50
|
||||||
@@ -1845,7 +1846,11 @@ Singleton {
|
|||||||
|
|
||||||
function addAppIdSubstitution(pattern, replacement, type) {
|
function addAppIdSubstitution(pattern, replacement, type) {
|
||||||
var subs = JSON.parse(JSON.stringify(appIdSubstitutions));
|
var subs = JSON.parse(JSON.stringify(appIdSubstitutions));
|
||||||
subs.push({ pattern: pattern, replacement: replacement, type: type });
|
subs.push({
|
||||||
|
pattern: pattern,
|
||||||
|
replacement: replacement,
|
||||||
|
type: type
|
||||||
|
});
|
||||||
appIdSubstitutions = subs;
|
appIdSubstitutions = subs;
|
||||||
saveSettings();
|
saveSettings();
|
||||||
}
|
}
|
||||||
@@ -1854,7 +1859,11 @@ Singleton {
|
|||||||
var subs = JSON.parse(JSON.stringify(appIdSubstitutions));
|
var subs = JSON.parse(JSON.stringify(appIdSubstitutions));
|
||||||
if (index < 0 || index >= subs.length)
|
if (index < 0 || index >= subs.length)
|
||||||
return;
|
return;
|
||||||
subs[index] = { pattern: pattern, replacement: replacement, type: type };
|
subs[index] = {
|
||||||
|
pattern: pattern,
|
||||||
|
replacement: replacement,
|
||||||
|
type: type
|
||||||
|
};
|
||||||
appIdSubstitutions = subs;
|
appIdSubstitutions = subs;
|
||||||
saveSettings();
|
saveSettings();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -268,6 +268,7 @@ var SPEC = {
|
|||||||
notificationTimeoutLow: { def: 5000 },
|
notificationTimeoutLow: { def: 5000 },
|
||||||
notificationTimeoutNormal: { def: 5000 },
|
notificationTimeoutNormal: { def: 5000 },
|
||||||
notificationTimeoutCritical: { def: 0 },
|
notificationTimeoutCritical: { def: 0 },
|
||||||
|
notificationCompactMode: { def: false },
|
||||||
notificationPopupPosition: { def: 0 },
|
notificationPopupPosition: { def: 0 },
|
||||||
notificationHistoryEnabled: { def: true },
|
notificationHistoryEnabled: { def: true },
|
||||||
notificationHistoryMaxCount: { def: 50 },
|
notificationHistoryMaxCount: { def: 50 },
|
||||||
|
|||||||
@@ -10,9 +10,17 @@ Rectangle {
|
|||||||
required property var historyItem
|
required property var historyItem
|
||||||
property bool isSelected: false
|
property bool isSelected: false
|
||||||
property bool keyboardNavigationActive: false
|
property bool keyboardNavigationActive: false
|
||||||
|
property bool descriptionExpanded: NotificationService.expandedMessages[historyItem?.id ? (historyItem.id + "_hist") : ""] || false
|
||||||
|
|
||||||
|
readonly property bool compactMode: SettingsData.notificationCompactMode
|
||||||
|
readonly property real cardPadding: compactMode ? Theme.spacingS : Theme.spacingM
|
||||||
|
readonly property real iconSize: compactMode ? 48 : 63
|
||||||
|
readonly property real contentSpacing: compactMode ? Theme.spacingXS : Theme.spacingS
|
||||||
|
readonly property real collapsedContentHeight: iconSize + cardPadding
|
||||||
|
readonly property real baseCardHeight: cardPadding * 2 + collapsedContentHeight
|
||||||
|
|
||||||
width: parent ? parent.width : 400
|
width: parent ? parent.width : 400
|
||||||
height: 116
|
height: baseCardHeight + contentItem.extraHeight
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
clip: true
|
clip: true
|
||||||
|
|
||||||
@@ -65,23 +73,28 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
id: contentItem
|
||||||
|
|
||||||
|
readonly property real expandedTextHeight: descriptionText.contentHeight
|
||||||
|
readonly property real twoLineHeight: descriptionText.font.pixelSize * 1.2 * 2
|
||||||
|
readonly property real extraHeight: (descriptionExpanded && expandedTextHeight > twoLineHeight + 2) ? (expandedTextHeight - twoLineHeight) : 0
|
||||||
|
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.topMargin: 12
|
anchors.topMargin: cardPadding
|
||||||
anchors.leftMargin: 16
|
anchors.leftMargin: Theme.spacingL
|
||||||
anchors.rightMargin: 56
|
anchors.rightMargin: Theme.spacingL + (compactMode ? 32 : 40)
|
||||||
height: 92
|
height: collapsedContentHeight + extraHeight
|
||||||
|
|
||||||
DankCircularImage {
|
DankCircularImage {
|
||||||
id: iconContainer
|
id: iconContainer
|
||||||
readonly property bool hasNotificationImage: historyItem.image && historyItem.image !== ""
|
readonly property bool hasNotificationImage: historyItem.image && historyItem.image !== ""
|
||||||
|
|
||||||
width: 63
|
width: iconSize
|
||||||
height: 63
|
height: iconSize
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.top: parent.top
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.topMargin: 14
|
|
||||||
|
|
||||||
imageSource: {
|
imageSource: {
|
||||||
if (hasNotificationImage)
|
if (hasNotificationImage)
|
||||||
@@ -116,60 +129,78 @@ Rectangle {
|
|||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors.left: iconContainer.right
|
anchors.left: iconContainer.right
|
||||||
anchors.leftMargin: 12
|
anchors.leftMargin: Theme.spacingM
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
anchors.bottomMargin: 8
|
anchors.bottomMargin: contentSpacing
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
|
|
||||||
Item {
|
Column {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: parent.height
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.top: parent.top
|
spacing: compactMode ? 1 : 2
|
||||||
anchors.topMargin: -2
|
|
||||||
|
|
||||||
Column {
|
StyledText {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
spacing: 2
|
text: {
|
||||||
|
const timeStr = NotificationService.formatHistoryTime(historyItem.timestamp);
|
||||||
|
const appName = historyItem.appName || "";
|
||||||
|
return timeStr.length > 0 ? `${appName} • ${timeStr}` : appName;
|
||||||
|
}
|
||||||
|
color: Theme.surfaceVariantText
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
font.weight: Font.Medium
|
||||||
|
elide: Text.ElideRight
|
||||||
|
maximumLineCount: 1
|
||||||
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
width: parent.width
|
text: historyItem.summary || ""
|
||||||
text: {
|
color: Theme.surfaceText
|
||||||
const timeStr = NotificationService.formatHistoryTime(historyItem.timestamp);
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
const appName = historyItem.appName || "";
|
font.weight: Font.Medium
|
||||||
return timeStr.length > 0 ? `${appName} • ${timeStr}` : appName;
|
width: parent.width
|
||||||
|
elide: Text.ElideRight
|
||||||
|
maximumLineCount: 1
|
||||||
|
visible: text.length > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
id: descriptionText
|
||||||
|
property bool hasMoreText: truncated
|
||||||
|
|
||||||
|
text: historyItem.htmlBody || historyItem.body || ""
|
||||||
|
color: Theme.surfaceVariantText
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
width: parent.width
|
||||||
|
elide: descriptionExpanded ? Text.ElideNone : Text.ElideRight
|
||||||
|
maximumLineCount: descriptionExpanded ? -1 : (compactMode ? 1 : 2)
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
visible: text.length > 0
|
||||||
|
linkColor: Theme.primary
|
||||||
|
onLinkActivated: link => Qt.openUrlExternally(link)
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : (parent.hasMoreText || descriptionExpanded) ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||||
|
|
||||||
|
onClicked: mouse => {
|
||||||
|
if (!parent.hoveredLink && (parent.hasMoreText || descriptionExpanded)) {
|
||||||
|
const messageId = historyItem?.id ? (historyItem.id + "_hist") : "";
|
||||||
|
NotificationService.toggleMessageExpansion(messageId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
color: Theme.surfaceVariantText
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
font.weight: Font.Medium
|
|
||||||
elide: Text.ElideRight
|
|
||||||
maximumLineCount: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
propagateComposedEvents: true
|
||||||
text: historyItem.summary || ""
|
onPressed: mouse => {
|
||||||
color: Theme.surfaceText
|
if (parent.hoveredLink)
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
mouse.accepted = false;
|
||||||
font.weight: Font.Medium
|
}
|
||||||
width: parent.width
|
onReleased: mouse => {
|
||||||
elide: Text.ElideRight
|
if (parent.hoveredLink)
|
||||||
maximumLineCount: 1
|
mouse.accepted = false;
|
||||||
visible: text.length > 0
|
}
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
id: descriptionText
|
|
||||||
text: historyItem.htmlBody || historyItem.body || ""
|
|
||||||
color: Theme.surfaceVariantText
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
width: parent.width
|
|
||||||
elide: Text.ElideRight
|
|
||||||
maximumLineCount: 2
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
visible: text.length > 0
|
|
||||||
linkColor: Theme.primary
|
|
||||||
onLinkActivated: link => Qt.openUrlExternally(link)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -179,11 +210,11 @@ Rectangle {
|
|||||||
DankActionButton {
|
DankActionButton {
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.topMargin: 12
|
anchors.topMargin: cardPadding
|
||||||
anchors.rightMargin: 16
|
anchors.rightMargin: Theme.spacingL
|
||||||
iconName: "close"
|
iconName: "close"
|
||||||
iconSize: 18
|
iconSize: compactMode ? 16 : 18
|
||||||
buttonSize: 28
|
buttonSize: compactMode ? 24 : 28
|
||||||
onClicked: NotificationService.removeFromHistory(historyItem.id)
|
onClicked: NotificationService.removeFromHistory(historyItem.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,17 +18,17 @@ Rectangle {
|
|||||||
property int selectedNotificationIndex: -1
|
property int selectedNotificationIndex: -1
|
||||||
property bool keyboardNavigationActive: false
|
property bool keyboardNavigationActive: false
|
||||||
|
|
||||||
|
readonly property bool compactMode: SettingsData.notificationCompactMode
|
||||||
|
readonly property real cardPadding: compactMode ? Theme.spacingS : Theme.spacingM
|
||||||
|
readonly property real iconSize: compactMode ? 48 : 63
|
||||||
|
readonly property real contentSpacing: compactMode ? Theme.spacingXS : Theme.spacingS
|
||||||
|
readonly property real badgeSize: compactMode ? 16 : 18
|
||||||
|
readonly property real actionButtonHeight: compactMode ? 20 : 24
|
||||||
|
readonly property real baseCardHeight: cardPadding * 2 + collapsedContentHeight
|
||||||
|
readonly property real collapsedContentHeight: iconSize + cardPadding
|
||||||
|
|
||||||
width: parent ? parent.width : 400
|
width: parent ? parent.width : 400
|
||||||
height: {
|
height: expanded ? (expandedContent.height + cardPadding * 2) : (baseCardHeight + collapsedContent.extraHeight)
|
||||||
if (expanded) {
|
|
||||||
return expandedContent.height + 28;
|
|
||||||
}
|
|
||||||
const baseHeight = 116;
|
|
||||||
if (descriptionExpanded) {
|
|
||||||
return baseHeight + descriptionText.contentHeight - (descriptionText.font.pixelSize * 1.2 * 2);
|
|
||||||
}
|
|
||||||
return baseHeight;
|
|
||||||
}
|
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
|
|
||||||
Behavior on border.color {
|
Behavior on border.color {
|
||||||
@@ -97,24 +97,28 @@ Rectangle {
|
|||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: collapsedContent
|
id: collapsedContent
|
||||||
|
|
||||||
|
readonly property real expandedTextHeight: descriptionText.contentHeight
|
||||||
|
readonly property real twoLineHeight: descriptionText.font.pixelSize * 1.2 * 2
|
||||||
|
readonly property real extraHeight: (descriptionExpanded && expandedTextHeight > twoLineHeight + 2) ? (expandedTextHeight - twoLineHeight) : 0
|
||||||
|
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.topMargin: 12
|
anchors.topMargin: cardPadding
|
||||||
anchors.leftMargin: 16
|
anchors.leftMargin: Theme.spacingL
|
||||||
anchors.rightMargin: 56
|
anchors.rightMargin: Theme.spacingL + (compactMode ? 32 : 40)
|
||||||
height: 92
|
height: collapsedContentHeight + extraHeight
|
||||||
visible: !expanded
|
visible: !expanded
|
||||||
|
|
||||||
DankCircularImage {
|
DankCircularImage {
|
||||||
id: iconContainer
|
id: iconContainer
|
||||||
readonly property bool hasNotificationImage: notificationGroup?.latestNotification?.image && notificationGroup.latestNotification.image !== ""
|
readonly property bool hasNotificationImage: notificationGroup?.latestNotification?.image && notificationGroup.latestNotification.image !== ""
|
||||||
|
|
||||||
width: 63
|
width: iconSize
|
||||||
height: 63
|
height: iconSize
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.top: parent.top
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.topMargin: 14
|
|
||||||
|
|
||||||
imageSource: {
|
imageSource: {
|
||||||
if (hasNotificationImage)
|
if (hasNotificationImage)
|
||||||
@@ -147,9 +151,9 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: 18
|
width: badgeSize
|
||||||
height: 18
|
height: badgeSize
|
||||||
radius: 9
|
radius: badgeSize / 2
|
||||||
color: Theme.primary
|
color: Theme.primary
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
@@ -161,7 +165,7 @@ Rectangle {
|
|||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: (notificationGroup?.count || 0) > 99 ? "99+" : (notificationGroup?.count || 0).toString()
|
text: (notificationGroup?.count || 0) > 99 ? "99+" : (notificationGroup?.count || 0).toString()
|
||||||
color: Theme.primaryText
|
color: Theme.primaryText
|
||||||
font.pixelSize: 9
|
font.pixelSize: compactMode ? 8 : 9
|
||||||
font.weight: Font.Bold
|
font.weight: Font.Bold
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -171,87 +175,78 @@ Rectangle {
|
|||||||
id: textContainer
|
id: textContainer
|
||||||
|
|
||||||
anchors.left: iconContainer.right
|
anchors.left: iconContainer.right
|
||||||
anchors.leftMargin: 12
|
anchors.leftMargin: Theme.spacingM
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: 0
|
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
anchors.bottomMargin: 8
|
anchors.bottomMargin: contentSpacing
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
|
|
||||||
Item {
|
Column {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: parent.height
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.top: parent.top
|
spacing: compactMode ? 1 : 2
|
||||||
anchors.topMargin: -2
|
|
||||||
|
|
||||||
Column {
|
StyledText {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
spacing: 2
|
text: {
|
||||||
|
const timeStr = (notificationGroup && notificationGroup.latestNotification && notificationGroup.latestNotification.timeStr) || "";
|
||||||
|
const appName = (notificationGroup && notificationGroup.appName) || "";
|
||||||
|
return timeStr.length > 0 ? `${appName} • ${timeStr}` : appName;
|
||||||
|
}
|
||||||
|
color: Theme.surfaceVariantText
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
font.weight: Font.Medium
|
||||||
|
elide: Text.ElideRight
|
||||||
|
maximumLineCount: 1
|
||||||
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
width: parent.width
|
text: (notificationGroup && notificationGroup.latestNotification && notificationGroup.latestNotification.summary) || ""
|
||||||
text: {
|
color: Theme.surfaceText
|
||||||
const timeStr = (notificationGroup && notificationGroup.latestNotification && notificationGroup.latestNotification.timeStr) || "";
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
const appName = (notificationGroup && notificationGroup.appName) || "";
|
font.weight: Font.Medium
|
||||||
return timeStr.length > 0 ? `${appName} • ${timeStr}` : appName;
|
width: parent.width
|
||||||
|
elide: Text.ElideRight
|
||||||
|
maximumLineCount: 1
|
||||||
|
visible: text.length > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
id: descriptionText
|
||||||
|
property string fullText: (notificationGroup && notificationGroup.latestNotification && notificationGroup.latestNotification.htmlBody) || ""
|
||||||
|
property bool hasMoreText: truncated
|
||||||
|
|
||||||
|
text: fullText
|
||||||
|
color: Theme.surfaceVariantText
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
width: parent.width
|
||||||
|
elide: Text.ElideRight
|
||||||
|
maximumLineCount: descriptionExpanded ? -1 : (compactMode ? 1 : 2)
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
visible: text.length > 0
|
||||||
|
linkColor: Theme.primary
|
||||||
|
onLinkActivated: link => Qt.openUrlExternally(link)
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : (parent.hasMoreText || descriptionExpanded) ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||||
|
|
||||||
|
onClicked: mouse => {
|
||||||
|
if (!parent.hoveredLink && (parent.hasMoreText || descriptionExpanded)) {
|
||||||
|
const messageId = (notificationGroup && notificationGroup.latestNotification && notificationGroup.latestNotification.notification && notificationGroup.latestNotification.notification.id) ? (notificationGroup.latestNotification.notification.id + "_desc") : "";
|
||||||
|
NotificationService.toggleMessageExpansion(messageId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
color: Theme.surfaceVariantText
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
font.weight: Font.Medium
|
|
||||||
elide: Text.ElideRight
|
|
||||||
maximumLineCount: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
propagateComposedEvents: true
|
||||||
text: (notificationGroup && notificationGroup.latestNotification && notificationGroup.latestNotification.summary) || ""
|
onPressed: mouse => {
|
||||||
color: Theme.surfaceText
|
if (parent.hoveredLink)
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
mouse.accepted = false;
|
||||||
font.weight: Font.Medium
|
}
|
||||||
width: parent.width
|
onReleased: mouse => {
|
||||||
elide: Text.ElideRight
|
if (parent.hoveredLink)
|
||||||
maximumLineCount: 1
|
mouse.accepted = false;
|
||||||
visible: text.length > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
id: descriptionText
|
|
||||||
property string fullText: (notificationGroup && notificationGroup.latestNotification && notificationGroup.latestNotification.htmlBody) || ""
|
|
||||||
property bool hasMoreText: truncated
|
|
||||||
|
|
||||||
text: fullText
|
|
||||||
color: Theme.surfaceVariantText
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
width: parent.width
|
|
||||||
elide: Text.ElideRight
|
|
||||||
maximumLineCount: descriptionExpanded ? -1 : 2
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
visible: text.length > 0
|
|
||||||
linkColor: Theme.primary
|
|
||||||
onLinkActivated: link => Qt.openUrlExternally(link)
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : (parent.hasMoreText || descriptionExpanded) ? Qt.PointingHandCursor : Qt.ArrowCursor
|
|
||||||
|
|
||||||
onClicked: mouse => {
|
|
||||||
if (!parent.hoveredLink && (parent.hasMoreText || descriptionExpanded)) {
|
|
||||||
const messageId = (notificationGroup && notificationGroup.latestNotification && notificationGroup.latestNotification.notification && notificationGroup.latestNotification.notification.id) ? (notificationGroup.latestNotification.notification.id + "_desc") : "";
|
|
||||||
NotificationService.toggleMessageExpansion(messageId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
propagateComposedEvents: true
|
|
||||||
onPressed: mouse => {
|
|
||||||
if (parent.hoveredLink) {
|
|
||||||
mouse.accepted = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onReleased: mouse => {
|
|
||||||
if (parent.hoveredLink) {
|
|
||||||
mouse.accepted = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -265,21 +260,20 @@ Rectangle {
|
|||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.topMargin: 14
|
anchors.topMargin: cardPadding
|
||||||
anchors.bottomMargin: 14
|
|
||||||
anchors.leftMargin: Theme.spacingL
|
anchors.leftMargin: Theme.spacingL
|
||||||
anchors.rightMargin: Theme.spacingL
|
anchors.rightMargin: Theme.spacingL
|
||||||
spacing: -1
|
spacing: compactMode ? Theme.spacingXS : Theme.spacingS
|
||||||
visible: expanded
|
visible: expanded
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: 40
|
height: compactMode ? 32 : 40
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: 56
|
anchors.rightMargin: Theme.spacingL + (compactMode ? 32 : 40)
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
spacing: Theme.spacingS
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
@@ -294,9 +288,9 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: 18
|
width: badgeSize
|
||||||
height: 18
|
height: badgeSize
|
||||||
radius: 9
|
radius: badgeSize / 2
|
||||||
color: Theme.primary
|
color: Theme.primary
|
||||||
visible: (notificationGroup?.count || 0) > 1
|
visible: (notificationGroup?.count || 0) > 1
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -305,7 +299,7 @@ Rectangle {
|
|||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: (notificationGroup?.count || 0) > 99 ? "99+" : (notificationGroup?.count || 0).toString()
|
text: (notificationGroup?.count || 0) > 99 ? "99+" : (notificationGroup?.count || 0).toString()
|
||||||
color: Theme.primaryText
|
color: Theme.primaryText
|
||||||
font.pixelSize: 9
|
font.pixelSize: compactMode ? 8 : 9
|
||||||
font.weight: Font.Bold
|
font.weight: Font.Bold
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -314,7 +308,7 @@ Rectangle {
|
|||||||
|
|
||||||
Column {
|
Column {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
spacing: 16
|
spacing: compactMode ? Theme.spacingS : Theme.spacingL
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
id: notificationRepeater
|
id: notificationRepeater
|
||||||
@@ -328,23 +322,23 @@ Rectangle {
|
|||||||
required property int index
|
required property int index
|
||||||
readonly property bool messageExpanded: NotificationService.expandedMessages[modelData?.notification?.id] || false
|
readonly property bool messageExpanded: NotificationService.expandedMessages[modelData?.notification?.id] || false
|
||||||
readonly property bool isSelected: root.selectedNotificationIndex === index
|
readonly property bool isSelected: root.selectedNotificationIndex === index
|
||||||
|
readonly property real expandedIconSize: compactMode ? 40 : 48
|
||||||
|
readonly property real expandedItemPadding: compactMode ? Theme.spacingS : Theme.spacingM
|
||||||
|
readonly property real expandedBaseHeight: expandedItemPadding * 2 + expandedIconSize + actionButtonHeight + contentSpacing * 2
|
||||||
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: {
|
height: {
|
||||||
const baseHeight = 120;
|
if (!messageExpanded)
|
||||||
if (messageExpanded) {
|
return expandedBaseHeight;
|
||||||
const twoLineHeight = bodyText.font.pixelSize * 1.2 * 2;
|
const twoLineHeight = bodyText.font.pixelSize * 1.2 * 2;
|
||||||
if (bodyText.implicitHeight > twoLineHeight + 2) {
|
if (bodyText.implicitHeight > twoLineHeight + 2)
|
||||||
const extraHeight = bodyText.implicitHeight - twoLineHeight;
|
return expandedBaseHeight + bodyText.implicitHeight - twoLineHeight;
|
||||||
return baseHeight + extraHeight;
|
return expandedBaseHeight;
|
||||||
}
|
|
||||||
}
|
|
||||||
return baseHeight;
|
|
||||||
}
|
}
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: isSelected ? Theme.primaryPressed : Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
|
color: isSelected ? Theme.primaryPressed : Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
|
||||||
border.color: isSelected ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.4) : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05)
|
border.color: isSelected ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.4) : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05)
|
||||||
border.width: isSelected ? 1 : 1
|
border.width: 1
|
||||||
|
|
||||||
Behavior on border.color {
|
Behavior on border.color {
|
||||||
ColorAnimation {
|
ColorAnimation {
|
||||||
@@ -359,19 +353,19 @@ Rectangle {
|
|||||||
|
|
||||||
Item {
|
Item {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: 12
|
anchors.margins: compactMode ? Theme.spacingS : Theme.spacingM
|
||||||
anchors.bottomMargin: 8
|
anchors.bottomMargin: contentSpacing
|
||||||
|
|
||||||
DankCircularImage {
|
DankCircularImage {
|
||||||
id: messageIcon
|
id: messageIcon
|
||||||
|
|
||||||
readonly property bool hasNotificationImage: modelData?.image && modelData.image !== ""
|
readonly property bool hasNotificationImage: modelData?.image && modelData.image !== ""
|
||||||
|
|
||||||
width: 48
|
width: expandedIconSize
|
||||||
height: 48
|
height: expandedIconSize
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.topMargin: 32
|
anchors.topMargin: compactMode ? Theme.spacingM : Theme.spacingXL
|
||||||
|
|
||||||
imageSource: {
|
imageSource: {
|
||||||
if (hasNotificationImage)
|
if (hasNotificationImage)
|
||||||
@@ -397,9 +391,9 @@ Rectangle {
|
|||||||
|
|
||||||
Item {
|
Item {
|
||||||
anchors.left: messageIcon.right
|
anchors.left: messageIcon.right
|
||||||
anchors.leftMargin: 12
|
anchors.leftMargin: Theme.spacingM
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: 12
|
anchors.rightMargin: Theme.spacingM
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
|
|
||||||
@@ -408,8 +402,8 @@ Rectangle {
|
|||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.bottom: buttonArea.top
|
anchors.bottom: buttonArea.top
|
||||||
anchors.bottomMargin: 4
|
anchors.bottomMargin: contentSpacing
|
||||||
spacing: 2
|
spacing: compactMode ? 1 : 2
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
@@ -477,12 +471,12 @@ Rectangle {
|
|||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
height: 30
|
height: actionButtonHeight + contentSpacing
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
spacing: 8
|
spacing: contentSpacing
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
model: modelData?.actions || []
|
model: modelData?.actions || []
|
||||||
@@ -490,18 +484,17 @@ Rectangle {
|
|||||||
Rectangle {
|
Rectangle {
|
||||||
property bool isHovered: false
|
property bool isHovered: false
|
||||||
|
|
||||||
width: Math.max(actionText.implicitWidth + 12, 50)
|
width: Math.max(actionText.implicitWidth + Theme.spacingM, compactMode ? 40 : 50)
|
||||||
height: 24
|
height: actionButtonHeight
|
||||||
radius: 4
|
radius: Theme.spacingXS
|
||||||
color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1) : "transparent"
|
color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1) : "transparent"
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
id: actionText
|
id: actionText
|
||||||
text: {
|
text: {
|
||||||
const baseText = modelData.text || "View";
|
const baseText = modelData.text || "View";
|
||||||
if (keyboardNavigationActive && (isGroupSelected || selectedNotificationIndex >= 0)) {
|
if (keyboardNavigationActive && (isGroupSelected || selectedNotificationIndex >= 0))
|
||||||
return `${baseText} (${index + 1})`;
|
return `${baseText} (${index + 1})`;
|
||||||
}
|
|
||||||
return baseText;
|
return baseText;
|
||||||
}
|
}
|
||||||
color: parent.isHovered ? Theme.primary : Theme.surfaceVariantText
|
color: parent.isHovered ? Theme.primary : Theme.surfaceVariantText
|
||||||
@@ -518,9 +511,8 @@ Rectangle {
|
|||||||
onEntered: parent.isHovered = true
|
onEntered: parent.isHovered = true
|
||||||
onExited: parent.isHovered = false
|
onExited: parent.isHovered = false
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (modelData && modelData.invoke) {
|
if (modelData && modelData.invoke)
|
||||||
modelData.invoke();
|
modelData.invoke();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -529,9 +521,9 @@ Rectangle {
|
|||||||
Rectangle {
|
Rectangle {
|
||||||
property bool isHovered: false
|
property bool isHovered: false
|
||||||
|
|
||||||
width: Math.max(clearText.implicitWidth + 12, 50)
|
width: Math.max(clearText.implicitWidth + Theme.spacingM, compactMode ? 40 : 50)
|
||||||
height: 24
|
height: actionButtonHeight
|
||||||
radius: 4
|
radius: Theme.spacingXS
|
||||||
color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1) : "transparent"
|
color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1) : "transparent"
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
@@ -564,10 +556,10 @@ Rectangle {
|
|||||||
Row {
|
Row {
|
||||||
visible: !expanded
|
visible: !expanded
|
||||||
anchors.right: clearButton.left
|
anchors.right: clearButton.left
|
||||||
anchors.rightMargin: 8
|
anchors.rightMargin: contentSpacing
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
anchors.bottomMargin: 8
|
anchors.bottomMargin: contentSpacing
|
||||||
spacing: 8
|
spacing: contentSpacing
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
model: notificationGroup?.latestNotification?.actions || []
|
model: notificationGroup?.latestNotification?.actions || []
|
||||||
@@ -575,9 +567,9 @@ Rectangle {
|
|||||||
Rectangle {
|
Rectangle {
|
||||||
property bool isHovered: false
|
property bool isHovered: false
|
||||||
|
|
||||||
width: Math.max(actionText.implicitWidth + 12, 50)
|
width: Math.max(actionText.implicitWidth + Theme.spacingM, compactMode ? 40 : 50)
|
||||||
height: 24
|
height: actionButtonHeight
|
||||||
radius: 4
|
radius: Theme.spacingXS
|
||||||
color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1) : "transparent"
|
color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1) : "transparent"
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
@@ -619,12 +611,12 @@ Rectangle {
|
|||||||
|
|
||||||
visible: !expanded
|
visible: !expanded
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: 16
|
anchors.rightMargin: Theme.spacingL
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
anchors.bottomMargin: 8
|
anchors.bottomMargin: contentSpacing
|
||||||
width: Math.max(clearText.implicitWidth + 12, 50)
|
width: Math.max(clearText.implicitWidth + Theme.spacingM, compactMode ? 40 : 50)
|
||||||
height: 24
|
height: actionButtonHeight
|
||||||
radius: 4
|
radius: Theme.spacingXS
|
||||||
color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1) : "transparent"
|
color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1) : "transparent"
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
@@ -660,18 +652,18 @@ Rectangle {
|
|||||||
id: fixedControls
|
id: fixedControls
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.topMargin: 12
|
anchors.topMargin: cardPadding
|
||||||
anchors.rightMargin: 16
|
anchors.rightMargin: Theme.spacingL
|
||||||
width: 60
|
width: compactMode ? 52 : 60
|
||||||
height: 28
|
height: compactMode ? 24 : 28
|
||||||
|
|
||||||
DankActionButton {
|
DankActionButton {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
visible: (notificationGroup?.count || 0) > 1
|
visible: (notificationGroup?.count || 0) > 1
|
||||||
iconName: expanded ? "expand_less" : "expand_more"
|
iconName: expanded ? "expand_less" : "expand_more"
|
||||||
iconSize: 18
|
iconSize: compactMode ? 16 : 18
|
||||||
buttonSize: 28
|
buttonSize: compactMode ? 24 : 28
|
||||||
onClicked: {
|
onClicked: {
|
||||||
root.userInitiatedExpansion = true;
|
root.userInitiatedExpansion = true;
|
||||||
NotificationService.toggleGroupExpansion(notificationGroup?.key || "");
|
NotificationService.toggleGroupExpansion(notificationGroup?.key || "");
|
||||||
@@ -682,8 +674,8 @@ Rectangle {
|
|||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
iconName: "close"
|
iconName: "close"
|
||||||
iconSize: 18
|
iconSize: compactMode ? 16 : 18
|
||||||
buttonSize: 28
|
buttonSize: compactMode ? 24 : 28
|
||||||
onClicked: NotificationService.dismissGroup(notificationGroup?.key || "")
|
onClicked: NotificationService.dismissGroup(notificationGroup?.key || "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,15 @@ PanelWindow {
|
|||||||
property bool _isDestroying: false
|
property bool _isDestroying: false
|
||||||
property bool _finalized: false
|
property bool _finalized: false
|
||||||
readonly property string clearText: I18n.tr("Dismiss")
|
readonly property string clearText: I18n.tr("Dismiss")
|
||||||
|
property bool descriptionExpanded: false
|
||||||
|
|
||||||
|
readonly property bool compactMode: SettingsData.notificationCompactMode
|
||||||
|
readonly property real cardPadding: compactMode ? Theme.spacingS : Theme.spacingM
|
||||||
|
readonly property real popupIconSize: compactMode ? 48 : 63
|
||||||
|
readonly property real contentSpacing: compactMode ? Theme.spacingXS : Theme.spacingS
|
||||||
|
readonly property real actionButtonHeight: compactMode ? 20 : 24
|
||||||
|
readonly property real collapsedContentHeight: popupIconSize + cardPadding
|
||||||
|
readonly property real basePopupHeight: cardPadding * 2 + collapsedContentHeight + Theme.spacingS
|
||||||
|
|
||||||
signal entered
|
signal entered
|
||||||
signal exitStarted
|
signal exitStarted
|
||||||
@@ -92,7 +101,15 @@ PanelWindow {
|
|||||||
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
|
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
implicitWidth: 400
|
implicitWidth: 400
|
||||||
implicitHeight: 122
|
implicitHeight: {
|
||||||
|
if (!descriptionExpanded)
|
||||||
|
return basePopupHeight;
|
||||||
|
const bodyTextHeight = bodyTextLoader.item?.contentHeight || 0;
|
||||||
|
const twoLineHeight = Theme.fontSizeSmall * 1.2 * 2;
|
||||||
|
if (bodyTextHeight > twoLineHeight + 2)
|
||||||
|
return basePopupHeight + bodyTextHeight - twoLineHeight;
|
||||||
|
return basePopupHeight;
|
||||||
|
}
|
||||||
onHasValidDataChanged: {
|
onHasValidDataChanged: {
|
||||||
if (!hasValidData && !exiting && !_isDestroying) {
|
if (!hasValidData && !exiting && !_isDestroying) {
|
||||||
forceExit();
|
forceExit();
|
||||||
@@ -352,13 +369,17 @@ PanelWindow {
|
|||||||
Item {
|
Item {
|
||||||
id: notificationContent
|
id: notificationContent
|
||||||
|
|
||||||
|
readonly property real expandedTextHeight: bodyTextLoader.item?.contentHeight || 0
|
||||||
|
readonly property real twoLineHeight: Theme.fontSizeSmall * 1.2 * 2
|
||||||
|
readonly property real extraHeight: (descriptionExpanded && expandedTextHeight > twoLineHeight + 2) ? (expandedTextHeight - twoLineHeight) : 0
|
||||||
|
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.topMargin: 12
|
anchors.topMargin: cardPadding
|
||||||
anchors.leftMargin: 16
|
anchors.leftMargin: Theme.spacingL
|
||||||
anchors.rightMargin: 56
|
anchors.rightMargin: Theme.spacingL + (compactMode ? 32 : 40)
|
||||||
height: 98
|
height: collapsedContentHeight + extraHeight
|
||||||
|
|
||||||
DankCircularImage {
|
DankCircularImage {
|
||||||
id: iconContainer
|
id: iconContainer
|
||||||
@@ -366,8 +387,8 @@ PanelWindow {
|
|||||||
readonly property bool hasNotificationImage: notificationData && notificationData.image && notificationData.image !== ""
|
readonly property bool hasNotificationImage: notificationData && notificationData.image && notificationData.image !== ""
|
||||||
readonly property bool needsImagePersist: hasNotificationImage && notificationData.image.startsWith("image://qsimage/") && !notificationData.persistedImagePath
|
readonly property bool needsImagePersist: hasNotificationImage && notificationData.image.startsWith("image://qsimage/") && !notificationData.persistedImagePath
|
||||||
|
|
||||||
width: 63
|
width: popupIconSize
|
||||||
height: 63
|
height: popupIconSize
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
@@ -416,76 +437,85 @@ PanelWindow {
|
|||||||
id: textContainer
|
id: textContainer
|
||||||
|
|
||||||
anchors.left: iconContainer.right
|
anchors.left: iconContainer.right
|
||||||
anchors.leftMargin: 12
|
anchors.leftMargin: Theme.spacingM
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: 0
|
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
anchors.bottomMargin: 8
|
anchors.bottomMargin: contentSpacing
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
|
|
||||||
Item {
|
Column {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: parent.height
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.top: parent.top
|
spacing: compactMode ? 1 : 2
|
||||||
anchors.topMargin: -2
|
|
||||||
|
|
||||||
Column {
|
StyledText {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
spacing: 2
|
text: {
|
||||||
|
if (!notificationData)
|
||||||
StyledText {
|
return "";
|
||||||
width: parent.width
|
const appName = notificationData.appName || "";
|
||||||
text: {
|
const timeStr = notificationData.timeStr || "";
|
||||||
if (!notificationData)
|
return timeStr.length > 0 ? appName + " • " + timeStr : appName;
|
||||||
return "";
|
|
||||||
|
|
||||||
const appName = notificationData.appName || "";
|
|
||||||
const timeStr = notificationData.timeStr || "";
|
|
||||||
if (timeStr.length > 0)
|
|
||||||
return appName + " • " + timeStr;
|
|
||||||
else
|
|
||||||
return appName;
|
|
||||||
}
|
|
||||||
color: Theme.surfaceVariantText
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
font.weight: Font.Medium
|
|
||||||
elide: Text.ElideRight
|
|
||||||
horizontalAlignment: Text.AlignLeft
|
|
||||||
maximumLineCount: 1
|
|
||||||
}
|
}
|
||||||
|
color: Theme.surfaceVariantText
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
font.weight: Font.Medium
|
||||||
|
elide: Text.ElideRight
|
||||||
|
horizontalAlignment: Text.AlignLeft
|
||||||
|
maximumLineCount: 1
|
||||||
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: notificationData ? (notificationData.summary || "") : ""
|
text: notificationData ? (notificationData.summary || "") : ""
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
width: parent.width
|
width: parent.width
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
horizontalAlignment: Text.AlignLeft
|
horizontalAlignment: Text.AlignLeft
|
||||||
maximumLineCount: 1
|
maximumLineCount: 1
|
||||||
visible: text.length > 0
|
visible: text.length > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: bodyTextLoader
|
||||||
|
width: parent.width
|
||||||
|
active: notificationData && (notificationData.htmlBody || "").length > 0
|
||||||
|
|
||||||
|
sourceComponent: StyledText {
|
||||||
|
id: bodyText
|
||||||
|
property bool hasMoreText: truncated
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: notificationData ? (notificationData.htmlBody || "") : ""
|
text: notificationData ? (notificationData.htmlBody || "") : ""
|
||||||
color: Theme.surfaceVariantText
|
color: Theme.surfaceVariantText
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
width: parent.width
|
width: parent.width
|
||||||
elide: Text.ElideRight
|
elide: descriptionExpanded ? Text.ElideNone : Text.ElideRight
|
||||||
horizontalAlignment: Text.AlignLeft
|
horizontalAlignment: Text.AlignLeft
|
||||||
maximumLineCount: 2
|
maximumLineCount: descriptionExpanded ? -1 : (compactMode ? 1 : 2)
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
visible: text.length > 0
|
|
||||||
linkColor: Theme.primary
|
linkColor: Theme.primary
|
||||||
onLinkActivated: link => {
|
onLinkActivated: link => Qt.openUrlExternally(link)
|
||||||
return Qt.openUrlExternally(link);
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
acceptedButtons: Qt.NoButton
|
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : (parent.hasMoreText || descriptionExpanded) ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||||
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
|
|
||||||
|
onClicked: mouse => {
|
||||||
|
if (!parent.hoveredLink && (parent.hasMoreText || descriptionExpanded))
|
||||||
|
win.descriptionExpanded = !win.descriptionExpanded;
|
||||||
|
}
|
||||||
|
|
||||||
|
propagateComposedEvents: true
|
||||||
|
onPressed: mouse => {
|
||||||
|
if (parent.hoveredLink)
|
||||||
|
mouse.accepted = false;
|
||||||
|
}
|
||||||
|
onReleased: mouse => {
|
||||||
|
if (parent.hoveredLink)
|
||||||
|
mouse.accepted = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -498,11 +528,11 @@ PanelWindow {
|
|||||||
|
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.topMargin: 12
|
anchors.topMargin: cardPadding
|
||||||
anchors.rightMargin: 16
|
anchors.rightMargin: Theme.spacingL
|
||||||
iconName: "close"
|
iconName: "close"
|
||||||
iconSize: 18
|
iconSize: compactMode ? 16 : 18
|
||||||
buttonSize: 28
|
buttonSize: compactMode ? 24 : 28
|
||||||
z: 15
|
z: 15
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (notificationData && !win.exiting)
|
if (notificationData && !win.exiting)
|
||||||
@@ -512,10 +542,10 @@ PanelWindow {
|
|||||||
|
|
||||||
Row {
|
Row {
|
||||||
anchors.right: clearButton.left
|
anchors.right: clearButton.left
|
||||||
anchors.rightMargin: 8
|
anchors.rightMargin: contentSpacing
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
anchors.bottomMargin: 8
|
anchors.bottomMargin: contentSpacing
|
||||||
spacing: 8
|
spacing: contentSpacing
|
||||||
z: 20
|
z: 20
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
@@ -524,9 +554,9 @@ PanelWindow {
|
|||||||
Rectangle {
|
Rectangle {
|
||||||
property bool isHovered: false
|
property bool isHovered: false
|
||||||
|
|
||||||
width: Math.max(actionText.implicitWidth + 12, 50)
|
width: Math.max(actionText.implicitWidth + Theme.spacingM, compactMode ? 40 : 50)
|
||||||
height: 24
|
height: actionButtonHeight
|
||||||
radius: 4
|
radius: Theme.spacingXS
|
||||||
color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1) : "transparent"
|
color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1) : "transparent"
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
@@ -550,7 +580,6 @@ PanelWindow {
|
|||||||
onClicked: {
|
onClicked: {
|
||||||
if (modelData && modelData.invoke)
|
if (modelData && modelData.invoke)
|
||||||
modelData.invoke();
|
modelData.invoke();
|
||||||
|
|
||||||
if (notificationData && !win.exiting)
|
if (notificationData && !win.exiting)
|
||||||
notificationData.popup = false;
|
notificationData.popup = false;
|
||||||
}
|
}
|
||||||
@@ -565,12 +594,12 @@ PanelWindow {
|
|||||||
property bool isHovered: false
|
property bool isHovered: false
|
||||||
|
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: 16
|
anchors.rightMargin: Theme.spacingL
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
anchors.bottomMargin: 8
|
anchors.bottomMargin: contentSpacing
|
||||||
width: Math.max(clearTextLabel.implicitWidth + 12, 50)
|
width: Math.max(clearTextLabel.implicitWidth + Theme.spacingM, compactMode ? 40 : 50)
|
||||||
height: 24
|
height: actionButtonHeight
|
||||||
radius: 4
|
radius: Theme.spacingXS
|
||||||
color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1) : "transparent"
|
color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1) : "transparent"
|
||||||
z: 20
|
z: 20
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
|
import qs.Common
|
||||||
import qs.Services
|
import qs.Services
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
@@ -6,7 +7,11 @@ QtObject {
|
|||||||
|
|
||||||
property var modelData
|
property var modelData
|
||||||
property int topMargin: 0
|
property int topMargin: 0
|
||||||
property int baseNotificationHeight: 120
|
readonly property bool compactMode: SettingsData.notificationCompactMode
|
||||||
|
readonly property real cardPadding: compactMode ? Theme.spacingS : Theme.spacingM
|
||||||
|
readonly property real popupIconSize: compactMode ? 48 : 63
|
||||||
|
readonly property real popupSpacing: Theme.spacingS
|
||||||
|
readonly property int baseNotificationHeight: cardPadding * 3 + popupIconSize + popupSpacing
|
||||||
property int maxTargetNotifications: 4
|
property int maxTargetNotifications: 4
|
||||||
property var popupWindows: [] // strong refs to windows (live until exitFinished)
|
property var popupWindows: [] // strong refs to windows (live until exitFinished)
|
||||||
property var destroyingWindows: new Set()
|
property var destroyingWindows: new Set()
|
||||||
|
|||||||
@@ -144,6 +144,15 @@ Item {
|
|||||||
checked: SettingsData.notificationOverlayEnabled
|
checked: SettingsData.notificationOverlayEnabled
|
||||||
onToggled: checked => SettingsData.set("notificationOverlayEnabled", checked)
|
onToggled: checked => SettingsData.set("notificationOverlayEnabled", checked)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SettingsToggleRow {
|
||||||
|
settingKey: "notificationCompactMode"
|
||||||
|
tags: ["notification", "compact", "size", "display", "mode"]
|
||||||
|
text: I18n.tr("Compact")
|
||||||
|
description: I18n.tr("Use smaller notification cards")
|
||||||
|
checked: SettingsData.notificationCompactMode
|
||||||
|
onToggled: checked => SettingsData.set("notificationCompactMode", checked)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsCard {
|
SettingsCard {
|
||||||
|
|||||||
Reference in New Issue
Block a user