mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-27 06:52:50 -05:00
qmlfmt with 4 space
This commit is contained in:
@@ -10,514 +10,519 @@ import qs.Common
|
||||
import "../Common/markdown2html.js" as Markdown2Html
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
id: root
|
||||
|
||||
readonly property list<NotifWrapper> notifications: []
|
||||
readonly property list<NotifWrapper> allWrappers: []
|
||||
readonly property list<NotifWrapper> popups: allWrappers.filter(n => n.popup)
|
||||
readonly property list<NotifWrapper> notifications: []
|
||||
readonly property list<NotifWrapper> allWrappers: []
|
||||
readonly property list<NotifWrapper> popups: allWrappers.filter(
|
||||
n => n.popup)
|
||||
|
||||
property list<NotifWrapper> notificationQueue: []
|
||||
property list<NotifWrapper> visibleNotifications: []
|
||||
property int maxVisibleNotifications: 3
|
||||
property bool addGateBusy: false
|
||||
property int enterAnimMs: 400
|
||||
property int seqCounter: 0
|
||||
property bool bulkDismissing: false
|
||||
property list<NotifWrapper> notificationQueue: []
|
||||
property list<NotifWrapper> visibleNotifications: []
|
||||
property int maxVisibleNotifications: 3
|
||||
property bool addGateBusy: false
|
||||
property int enterAnimMs: 400
|
||||
property int seqCounter: 0
|
||||
property bool bulkDismissing: false
|
||||
|
||||
Timer {
|
||||
id: addGate
|
||||
interval: enterAnimMs + 50
|
||||
running: false
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
addGateBusy = false
|
||||
processQueue()
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: timeUpdateTimer
|
||||
interval: 30000
|
||||
repeat: true
|
||||
running: root.allWrappers.length > 0
|
||||
triggeredOnStart: false
|
||||
onTriggered: {
|
||||
root.timeUpdateTick = !root.timeUpdateTick
|
||||
}
|
||||
}
|
||||
|
||||
property bool timeUpdateTick: false
|
||||
property bool clockFormatChanged: false
|
||||
|
||||
readonly property var groupedNotifications: getGroupedNotifications()
|
||||
readonly property var groupedPopups: getGroupedPopups()
|
||||
|
||||
property var expandedGroups: ({})
|
||||
property var expandedMessages: ({})
|
||||
property bool popupsDisabled: false
|
||||
|
||||
NotificationServer {
|
||||
id: server
|
||||
|
||||
keepOnReload: false
|
||||
actionsSupported: true
|
||||
actionIconsSupported: true
|
||||
bodyHyperlinksSupported: true
|
||||
bodyImagesSupported: true
|
||||
bodyMarkupSupported: true
|
||||
imageSupported: true
|
||||
inlineReplySupported: true
|
||||
persistenceSupported: true
|
||||
|
||||
onNotification: notif => {
|
||||
notif.tracked = true
|
||||
|
||||
const shouldShowPopup = !root.popupsDisabled && !SessionData.doNotDisturb
|
||||
const wrapper = notifComponent.createObject(root, {
|
||||
"popup": shouldShowPopup,
|
||||
"notification": notif
|
||||
})
|
||||
|
||||
if (wrapper) {
|
||||
root.allWrappers.push(wrapper)
|
||||
root.notifications.push(wrapper)
|
||||
|
||||
if (shouldShowPopup) {
|
||||
notificationQueue = [...notificationQueue, wrapper]
|
||||
processQueue()
|
||||
Timer {
|
||||
id: addGate
|
||||
interval: enterAnimMs + 50
|
||||
running: false
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
addGateBusy = false
|
||||
processQueue()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component NotifWrapper: QtObject {
|
||||
id: wrapper
|
||||
|
||||
property bool popup: false
|
||||
property bool removedByLimit: false
|
||||
property bool isPersistent: true
|
||||
property int seq: 0
|
||||
|
||||
onPopupChanged: {
|
||||
if (!popup) {
|
||||
removeFromVisibleNotifications(wrapper)
|
||||
}
|
||||
}
|
||||
|
||||
readonly property Timer timer: Timer {
|
||||
interval: {
|
||||
if (!wrapper.notification) return 5000
|
||||
|
||||
switch (wrapper.notification.urgency) {
|
||||
case NotificationUrgency.Low:
|
||||
return SettingsData.notificationTimeoutLow
|
||||
case NotificationUrgency.Critical:
|
||||
return SettingsData.notificationTimeoutCritical
|
||||
default:
|
||||
return SettingsData.notificationTimeoutNormal
|
||||
Timer {
|
||||
id: timeUpdateTimer
|
||||
interval: 30000
|
||||
repeat: true
|
||||
running: root.allWrappers.length > 0
|
||||
triggeredOnStart: false
|
||||
onTriggered: {
|
||||
root.timeUpdateTick = !root.timeUpdateTick
|
||||
}
|
||||
}
|
||||
repeat: false
|
||||
running: false
|
||||
onTriggered: {
|
||||
if (interval > 0) {
|
||||
wrapper.popup = false
|
||||
}
|
||||
|
||||
property bool timeUpdateTick: false
|
||||
property bool clockFormatChanged: false
|
||||
|
||||
readonly property var groupedNotifications: getGroupedNotifications()
|
||||
readonly property var groupedPopups: getGroupedPopups()
|
||||
|
||||
property var expandedGroups: ({})
|
||||
property var expandedMessages: ({})
|
||||
property bool popupsDisabled: false
|
||||
|
||||
NotificationServer {
|
||||
id: server
|
||||
|
||||
keepOnReload: false
|
||||
actionsSupported: true
|
||||
actionIconsSupported: true
|
||||
bodyHyperlinksSupported: true
|
||||
bodyImagesSupported: true
|
||||
bodyMarkupSupported: true
|
||||
imageSupported: true
|
||||
inlineReplySupported: true
|
||||
persistenceSupported: true
|
||||
|
||||
onNotification: notif => {
|
||||
notif.tracked = true
|
||||
|
||||
const shouldShowPopup = !root.popupsDisabled
|
||||
&& !SessionData.doNotDisturb
|
||||
const wrapper = notifComponent.createObject(root, {
|
||||
"popup": shouldShowPopup,
|
||||
"notification": notif
|
||||
})
|
||||
|
||||
if (wrapper) {
|
||||
root.allWrappers.push(wrapper)
|
||||
root.notifications.push(wrapper)
|
||||
|
||||
if (shouldShowPopup) {
|
||||
notificationQueue = [...notificationQueue, wrapper]
|
||||
processQueue()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
readonly property date time: new Date()
|
||||
readonly property string timeStr: {
|
||||
root.timeUpdateTick
|
||||
root.clockFormatChanged
|
||||
|
||||
const now = new Date()
|
||||
const diff = now.getTime() - time.getTime()
|
||||
const minutes = Math.floor(diff / 60000)
|
||||
const hours = Math.floor(minutes / 60)
|
||||
|
||||
if (hours < 1) {
|
||||
if (minutes < 1)
|
||||
return "now"
|
||||
return `${minutes}m ago`
|
||||
}
|
||||
|
||||
const nowDate = new Date(now.getFullYear(), now.getMonth(), now.getDate())
|
||||
const timeDate = new Date(time.getFullYear(), time.getMonth(), time.getDate())
|
||||
const daysDiff = Math.floor((nowDate - timeDate) / (1000 * 60 * 60 * 24))
|
||||
|
||||
if (daysDiff === 0) {
|
||||
return formatTime(time)
|
||||
}
|
||||
|
||||
if (daysDiff === 1) {
|
||||
return `yesterday, ${formatTime(time)}`
|
||||
}
|
||||
|
||||
return `${daysDiff} days ago`
|
||||
}
|
||||
|
||||
function formatTime(date) {
|
||||
let use24Hour = true
|
||||
try {
|
||||
if (typeof SettingsData !== "undefined" && SettingsData.use24HourClock !== undefined) {
|
||||
use24Hour = SettingsData.use24HourClock
|
||||
}
|
||||
} catch (e) {
|
||||
use24Hour = true
|
||||
}
|
||||
|
||||
if (use24Hour) {
|
||||
return date.toLocaleTimeString(Qt.locale(), "HH:mm")
|
||||
} else {
|
||||
return date.toLocaleTimeString(Qt.locale(), "h:mm AP")
|
||||
}
|
||||
}
|
||||
|
||||
required property Notification notification
|
||||
readonly property string summary: notification.summary
|
||||
readonly property string body: notification.body
|
||||
readonly property string htmlBody: {
|
||||
if (body && (body.includes('<') && body.includes('>'))) {
|
||||
return body
|
||||
}
|
||||
return Markdown2Html.markdownToHtml(body)
|
||||
}
|
||||
readonly property string appIcon: notification.appIcon
|
||||
readonly property string appName: {
|
||||
if (notification.appName == "") {
|
||||
const entry = DesktopEntries.byId(notification.desktopEntry)
|
||||
if (entry && entry.name) {
|
||||
return entry.name.toLowerCase()
|
||||
}
|
||||
}
|
||||
return notification.appName || "app"
|
||||
}
|
||||
readonly property string desktopEntry: notification.desktopEntry
|
||||
readonly property string image: notification.image
|
||||
readonly property string cleanImage: {
|
||||
if (!image)
|
||||
return ""
|
||||
if (image.startsWith("file://")) {
|
||||
return image.substring(7)
|
||||
}
|
||||
return image
|
||||
}
|
||||
readonly property int urgency: notification.urgency
|
||||
readonly property list<NotificationAction> actions: notification.actions
|
||||
component NotifWrapper: QtObject {
|
||||
id: wrapper
|
||||
|
||||
property bool popup: false
|
||||
property bool removedByLimit: false
|
||||
property bool isPersistent: true
|
||||
property int seq: 0
|
||||
|
||||
readonly property Connections conn: Connections {
|
||||
target: wrapper.notification.Retainable
|
||||
|
||||
function onDropped(): void {
|
||||
const notifIndex = root.notifications.indexOf(wrapper)
|
||||
const allIndex = root.allWrappers.indexOf(wrapper)
|
||||
if (allIndex !== -1)
|
||||
root.allWrappers.splice(allIndex, 1)
|
||||
if (notifIndex !== -1)
|
||||
root.notifications.splice(notifIndex, 1)
|
||||
|
||||
if (root.bulkDismissing)
|
||||
return
|
||||
|
||||
const groupKey = getGroupKey(wrapper)
|
||||
const remainingInGroup = root.notifications.filter(n => getGroupKey(
|
||||
n) === groupKey)
|
||||
|
||||
if (remainingInGroup.length <= 1) {
|
||||
clearGroupExpansionState(groupKey)
|
||||
onPopupChanged: {
|
||||
if (!popup) {
|
||||
removeFromVisibleNotifications(wrapper)
|
||||
}
|
||||
}
|
||||
|
||||
cleanupExpansionStates()
|
||||
}
|
||||
|
||||
function onAboutToDestroy(): void {
|
||||
wrapper.destroy()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: notifComponent
|
||||
NotifWrapper {}
|
||||
}
|
||||
|
||||
function clearAllNotifications() {
|
||||
bulkDismissing = true
|
||||
popupsDisabled = true
|
||||
addGate.stop()
|
||||
addGateBusy = false
|
||||
notificationQueue = []
|
||||
|
||||
for (const w of visibleNotifications)
|
||||
w.popup = false
|
||||
visibleNotifications = []
|
||||
|
||||
const toDismiss = notifications.slice()
|
||||
|
||||
if (notifications.length)
|
||||
notifications.splice(0, notifications.length)
|
||||
expandedGroups = {}
|
||||
expandedMessages = {}
|
||||
|
||||
for (var i = 0; i < toDismiss.length; ++i) {
|
||||
const w = toDismiss[i]
|
||||
if (w && w.notification) {
|
||||
try {
|
||||
w.notification.dismiss()
|
||||
} catch (e) {
|
||||
readonly property Timer timer: Timer {
|
||||
interval: {
|
||||
if (!wrapper.notification)
|
||||
return 5000
|
||||
|
||||
switch (wrapper.notification.urgency) {
|
||||
case NotificationUrgency.Low:
|
||||
return SettingsData.notificationTimeoutLow
|
||||
case NotificationUrgency.Critical:
|
||||
return SettingsData.notificationTimeoutCritical
|
||||
default:
|
||||
return SettingsData.notificationTimeoutNormal
|
||||
}
|
||||
}
|
||||
repeat: false
|
||||
running: false
|
||||
onTriggered: {
|
||||
if (interval > 0) {
|
||||
wrapper.popup = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bulkDismissing = false
|
||||
popupsDisabled = false
|
||||
}
|
||||
readonly property date time: new Date()
|
||||
readonly property string timeStr: {
|
||||
root.timeUpdateTick
|
||||
root.clockFormatChanged
|
||||
|
||||
function dismissNotification(wrapper) {
|
||||
if (!wrapper || !wrapper.notification)
|
||||
return
|
||||
wrapper.popup = false
|
||||
wrapper.notification.dismiss()
|
||||
}
|
||||
const now = new Date()
|
||||
const diff = now.getTime() - time.getTime()
|
||||
const minutes = Math.floor(diff / 60000)
|
||||
const hours = Math.floor(minutes / 60)
|
||||
|
||||
function disablePopups(disable) {
|
||||
popupsDisabled = disable
|
||||
if (disable) {
|
||||
notificationQueue = []
|
||||
visibleNotifications = []
|
||||
for (const notif of root.allWrappers) {
|
||||
notif.popup = false
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hours < 1) {
|
||||
if (minutes < 1)
|
||||
return "now"
|
||||
return `${minutes}m ago`
|
||||
}
|
||||
|
||||
function processQueue() {
|
||||
if (addGateBusy)
|
||||
return
|
||||
if (popupsDisabled)
|
||||
return
|
||||
if (SessionData.doNotDisturb)
|
||||
return
|
||||
if (notificationQueue.length === 0)
|
||||
return
|
||||
const nowDate = new Date(now.getFullYear(), now.getMonth(),
|
||||
now.getDate())
|
||||
const timeDate = new Date(time.getFullYear(), time.getMonth(),
|
||||
time.getDate())
|
||||
const daysDiff = Math.floor(
|
||||
(nowDate - timeDate) / (1000 * 60 * 60 * 24))
|
||||
|
||||
const next = notificationQueue.shift()
|
||||
if (daysDiff === 0) {
|
||||
return formatTime(time)
|
||||
}
|
||||
|
||||
next.seq = ++seqCounter
|
||||
visibleNotifications = [...visibleNotifications, next]
|
||||
next.popup = true
|
||||
if (daysDiff === 1) {
|
||||
return `yesterday, ${formatTime(time)}`
|
||||
}
|
||||
|
||||
if (next.timer.interval > 0) {
|
||||
next.timer.start()
|
||||
}
|
||||
|
||||
addGateBusy = true
|
||||
addGate.restart()
|
||||
}
|
||||
|
||||
function removeFromVisibleNotifications(wrapper) {
|
||||
const i = visibleNotifications.findIndex(n => n === wrapper)
|
||||
if (i !== -1) {
|
||||
const v = [...visibleNotifications]
|
||||
v.splice(i, 1)
|
||||
visibleNotifications = v
|
||||
processQueue()
|
||||
}
|
||||
}
|
||||
|
||||
function releaseWrapper(w) {
|
||||
let v = visibleNotifications.slice()
|
||||
const vi = v.indexOf(w)
|
||||
if (vi !== -1) {
|
||||
v.splice(vi, 1)
|
||||
visibleNotifications = v
|
||||
}
|
||||
|
||||
let q = notificationQueue.slice()
|
||||
const qi = q.indexOf(w)
|
||||
if (qi !== -1) {
|
||||
q.splice(qi, 1)
|
||||
notificationQueue = q
|
||||
}
|
||||
|
||||
if (w && w.destroy && !w.isPersistent) {
|
||||
w.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
function getGroupKey(wrapper) {
|
||||
if (wrapper.desktopEntry && wrapper.desktopEntry !== "") {
|
||||
return wrapper.desktopEntry.toLowerCase()
|
||||
}
|
||||
|
||||
return wrapper.appName.toLowerCase()
|
||||
}
|
||||
|
||||
function getGroupedNotifications() {
|
||||
const groups = {}
|
||||
|
||||
for (const notif of notifications) {
|
||||
const groupKey = getGroupKey(notif)
|
||||
if (!groups[groupKey]) {
|
||||
groups[groupKey] = {
|
||||
"key": groupKey,
|
||||
"appName": notif.appName,
|
||||
"notifications": [],
|
||||
"latestNotification": null,
|
||||
"count": 0,
|
||||
"hasInlineReply": false
|
||||
return `${daysDiff} days ago`
|
||||
}
|
||||
}
|
||||
|
||||
groups[groupKey].notifications.unshift(notif)
|
||||
groups[groupKey].latestNotification = groups[groupKey].notifications[0]
|
||||
groups[groupKey].count = groups[groupKey].notifications.length
|
||||
function formatTime(date) {
|
||||
let use24Hour = true
|
||||
try {
|
||||
if (typeof SettingsData !== "undefined"
|
||||
&& SettingsData.use24HourClock !== undefined) {
|
||||
use24Hour = SettingsData.use24HourClock
|
||||
}
|
||||
} catch (e) {
|
||||
use24Hour = true
|
||||
}
|
||||
|
||||
if (notif.notification.hasInlineReply) {
|
||||
groups[groupKey].hasInlineReply = true
|
||||
}
|
||||
}
|
||||
|
||||
return Object.values(groups).sort((a, b) => {
|
||||
const aUrgency = a.latestNotification.urgency
|
||||
|| NotificationUrgency.Low
|
||||
const bUrgency = b.latestNotification.urgency
|
||||
|| NotificationUrgency.Low
|
||||
if (aUrgency !== bUrgency) {
|
||||
return bUrgency - aUrgency
|
||||
}
|
||||
return b.latestNotification.time.getTime(
|
||||
) - a.latestNotification.time.getTime(
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
function getGroupedPopups() {
|
||||
const groups = {}
|
||||
|
||||
for (const notif of popups) {
|
||||
const groupKey = getGroupKey(notif)
|
||||
if (!groups[groupKey]) {
|
||||
groups[groupKey] = {
|
||||
"key": groupKey,
|
||||
"appName": notif.appName,
|
||||
"notifications": [],
|
||||
"latestNotification": null,
|
||||
"count": 0,
|
||||
"hasInlineReply": false
|
||||
if (use24Hour) {
|
||||
return date.toLocaleTimeString(Qt.locale(), "HH:mm")
|
||||
} else {
|
||||
return date.toLocaleTimeString(Qt.locale(), "h:mm AP")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
groups[groupKey].notifications.unshift(notif)
|
||||
groups[groupKey].latestNotification = groups[groupKey].notifications[0]
|
||||
groups[groupKey].count = groups[groupKey].notifications.length
|
||||
|
||||
if (notif.notification.hasInlineReply) {
|
||||
groups[groupKey].hasInlineReply = true
|
||||
}
|
||||
}
|
||||
|
||||
return Object.values(groups).sort((a, b) => {
|
||||
return b.latestNotification.time.getTime(
|
||||
) - a.latestNotification.time.getTime(
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
function toggleGroupExpansion(groupKey) {
|
||||
let newExpandedGroups = {}
|
||||
for (const key in expandedGroups) {
|
||||
newExpandedGroups[key] = expandedGroups[key]
|
||||
}
|
||||
newExpandedGroups[groupKey] = !newExpandedGroups[groupKey]
|
||||
expandedGroups = newExpandedGroups
|
||||
}
|
||||
|
||||
function dismissGroup(groupKey) {
|
||||
const group = groupedNotifications.find(g => g.key === groupKey)
|
||||
if (group) {
|
||||
for (const notif of group.notifications) {
|
||||
if (notif && notif.notification) {
|
||||
notif.notification.dismiss()
|
||||
required property Notification notification
|
||||
readonly property string summary: notification.summary
|
||||
readonly property string body: notification.body
|
||||
readonly property string htmlBody: {
|
||||
if (body && (body.includes('<') && body.includes('>'))) {
|
||||
return body
|
||||
}
|
||||
return Markdown2Html.markdownToHtml(body)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const notif of allWrappers) {
|
||||
if (notif && notif.notification && getGroupKey(notif) === groupKey) {
|
||||
notif.notification.dismiss()
|
||||
readonly property string appIcon: notification.appIcon
|
||||
readonly property string appName: {
|
||||
if (notification.appName == "") {
|
||||
const entry = DesktopEntries.byId(notification.desktopEntry)
|
||||
if (entry && entry.name) {
|
||||
return entry.name.toLowerCase()
|
||||
}
|
||||
}
|
||||
return notification.appName || "app"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function clearGroupExpansionState(groupKey) {
|
||||
let newExpandedGroups = {}
|
||||
for (const key in expandedGroups) {
|
||||
if (key !== groupKey && expandedGroups[key]) {
|
||||
newExpandedGroups[key] = true
|
||||
}
|
||||
}
|
||||
expandedGroups = newExpandedGroups
|
||||
}
|
||||
|
||||
function cleanupExpansionStates() {
|
||||
const currentGroupKeys = new Set(groupedNotifications.map(g => g.key))
|
||||
const currentMessageIds = new Set()
|
||||
for (const group of groupedNotifications) {
|
||||
for (const notif of group.notifications) {
|
||||
currentMessageIds.add(notif.notification.id)
|
||||
}
|
||||
}
|
||||
let newExpandedGroups = {}
|
||||
for (const key in expandedGroups) {
|
||||
if (currentGroupKeys.has(key) && expandedGroups[key]) {
|
||||
newExpandedGroups[key] = true
|
||||
}
|
||||
}
|
||||
expandedGroups = newExpandedGroups
|
||||
let newExpandedMessages = {}
|
||||
for (const messageId in expandedMessages) {
|
||||
if (currentMessageIds.has(messageId) && expandedMessages[messageId]) {
|
||||
newExpandedMessages[messageId] = true
|
||||
}
|
||||
}
|
||||
expandedMessages = newExpandedMessages
|
||||
}
|
||||
|
||||
function toggleMessageExpansion(messageId) {
|
||||
let newExpandedMessages = {}
|
||||
for (const key in expandedMessages) {
|
||||
newExpandedMessages[key] = expandedMessages[key]
|
||||
}
|
||||
newExpandedMessages[messageId] = !newExpandedMessages[messageId]
|
||||
expandedMessages = newExpandedMessages
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: SessionData
|
||||
function onDoNotDisturbChanged() {
|
||||
if (SessionData.doNotDisturb) {
|
||||
// Hide all current popups when DND is enabled
|
||||
for (const notif of visibleNotifications) {
|
||||
notif.popup = false
|
||||
readonly property string desktopEntry: notification.desktopEntry
|
||||
readonly property string image: notification.image
|
||||
readonly property string cleanImage: {
|
||||
if (!image)
|
||||
return ""
|
||||
if (image.startsWith("file://")) {
|
||||
return image.substring(7)
|
||||
}
|
||||
return image
|
||||
}
|
||||
visibleNotifications = []
|
||||
readonly property int urgency: notification.urgency
|
||||
readonly property list<NotificationAction> actions: notification.actions
|
||||
|
||||
readonly property Connections conn: Connections {
|
||||
target: wrapper.notification.Retainable
|
||||
|
||||
function onDropped(): void {
|
||||
const notifIndex = root.notifications.indexOf(wrapper)
|
||||
const allIndex = root.allWrappers.indexOf(wrapper)
|
||||
if (allIndex !== -1)
|
||||
root.allWrappers.splice(allIndex, 1)
|
||||
if (notifIndex !== -1)
|
||||
root.notifications.splice(notifIndex, 1)
|
||||
|
||||
if (root.bulkDismissing)
|
||||
return
|
||||
|
||||
const groupKey = getGroupKey(wrapper)
|
||||
const remainingInGroup = root.notifications.filter(
|
||||
n => getGroupKey(n) === groupKey)
|
||||
|
||||
if (remainingInGroup.length <= 1) {
|
||||
clearGroupExpansionState(groupKey)
|
||||
}
|
||||
|
||||
cleanupExpansionStates()
|
||||
}
|
||||
|
||||
function onAboutToDestroy(): void {
|
||||
wrapper.destroy()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: notifComponent
|
||||
NotifWrapper {}
|
||||
}
|
||||
|
||||
function clearAllNotifications() {
|
||||
bulkDismissing = true
|
||||
popupsDisabled = true
|
||||
addGate.stop()
|
||||
addGateBusy = false
|
||||
notificationQueue = []
|
||||
} else {
|
||||
// Re-enable popup processing when DND is disabled
|
||||
processQueue()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: typeof SettingsData !== "undefined" ? SettingsData : null
|
||||
function onUse24HourClockChanged() {
|
||||
root.clockFormatChanged = !root.clockFormatChanged
|
||||
for (const w of visibleNotifications)
|
||||
w.popup = false
|
||||
visibleNotifications = []
|
||||
|
||||
const toDismiss = notifications.slice()
|
||||
|
||||
if (notifications.length)
|
||||
notifications.splice(0, notifications.length)
|
||||
expandedGroups = {}
|
||||
expandedMessages = {}
|
||||
|
||||
for (var i = 0; i < toDismiss.length; ++i) {
|
||||
const w = toDismiss[i]
|
||||
if (w && w.notification) {
|
||||
try {
|
||||
w.notification.dismiss()
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bulkDismissing = false
|
||||
popupsDisabled = false
|
||||
}
|
||||
|
||||
function dismissNotification(wrapper) {
|
||||
if (!wrapper || !wrapper.notification)
|
||||
return
|
||||
wrapper.popup = false
|
||||
wrapper.notification.dismiss()
|
||||
}
|
||||
|
||||
function disablePopups(disable) {
|
||||
popupsDisabled = disable
|
||||
if (disable) {
|
||||
notificationQueue = []
|
||||
visibleNotifications = []
|
||||
for (const notif of root.allWrappers) {
|
||||
notif.popup = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function processQueue() {
|
||||
if (addGateBusy)
|
||||
return
|
||||
if (popupsDisabled)
|
||||
return
|
||||
if (SessionData.doNotDisturb)
|
||||
return
|
||||
if (notificationQueue.length === 0)
|
||||
return
|
||||
|
||||
const next = notificationQueue.shift()
|
||||
|
||||
next.seq = ++seqCounter
|
||||
visibleNotifications = [...visibleNotifications, next]
|
||||
next.popup = true
|
||||
|
||||
if (next.timer.interval > 0) {
|
||||
next.timer.start()
|
||||
}
|
||||
|
||||
addGateBusy = true
|
||||
addGate.restart()
|
||||
}
|
||||
|
||||
function removeFromVisibleNotifications(wrapper) {
|
||||
const i = visibleNotifications.findIndex(n => n === wrapper)
|
||||
if (i !== -1) {
|
||||
const v = [...visibleNotifications]
|
||||
v.splice(i, 1)
|
||||
visibleNotifications = v
|
||||
processQueue()
|
||||
}
|
||||
}
|
||||
|
||||
function releaseWrapper(w) {
|
||||
let v = visibleNotifications.slice()
|
||||
const vi = v.indexOf(w)
|
||||
if (vi !== -1) {
|
||||
v.splice(vi, 1)
|
||||
visibleNotifications = v
|
||||
}
|
||||
|
||||
let q = notificationQueue.slice()
|
||||
const qi = q.indexOf(w)
|
||||
if (qi !== -1) {
|
||||
q.splice(qi, 1)
|
||||
notificationQueue = q
|
||||
}
|
||||
|
||||
if (w && w.destroy && !w.isPersistent) {
|
||||
w.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
function getGroupKey(wrapper) {
|
||||
if (wrapper.desktopEntry && wrapper.desktopEntry !== "") {
|
||||
return wrapper.desktopEntry.toLowerCase()
|
||||
}
|
||||
|
||||
return wrapper.appName.toLowerCase()
|
||||
}
|
||||
|
||||
function getGroupedNotifications() {
|
||||
const groups = {}
|
||||
|
||||
for (const notif of notifications) {
|
||||
const groupKey = getGroupKey(notif)
|
||||
if (!groups[groupKey]) {
|
||||
groups[groupKey] = {
|
||||
"key": groupKey,
|
||||
"appName": notif.appName,
|
||||
"notifications": [],
|
||||
"latestNotification": null,
|
||||
"count": 0,
|
||||
"hasInlineReply": false
|
||||
}
|
||||
}
|
||||
|
||||
groups[groupKey].notifications.unshift(notif)
|
||||
groups[groupKey].latestNotification = groups[groupKey].notifications[0]
|
||||
groups[groupKey].count = groups[groupKey].notifications.length
|
||||
|
||||
if (notif.notification.hasInlineReply) {
|
||||
groups[groupKey].hasInlineReply = true
|
||||
}
|
||||
}
|
||||
|
||||
return Object.values(groups).sort((a, b) => {
|
||||
const aUrgency = a.latestNotification.urgency
|
||||
|| NotificationUrgency.Low
|
||||
const bUrgency = b.latestNotification.urgency
|
||||
|| NotificationUrgency.Low
|
||||
if (aUrgency !== bUrgency) {
|
||||
return bUrgency - aUrgency
|
||||
}
|
||||
return b.latestNotification.time.getTime(
|
||||
) - a.latestNotification.time.getTime()
|
||||
})
|
||||
}
|
||||
|
||||
function getGroupedPopups() {
|
||||
const groups = {}
|
||||
|
||||
for (const notif of popups) {
|
||||
const groupKey = getGroupKey(notif)
|
||||
if (!groups[groupKey]) {
|
||||
groups[groupKey] = {
|
||||
"key": groupKey,
|
||||
"appName": notif.appName,
|
||||
"notifications": [],
|
||||
"latestNotification": null,
|
||||
"count": 0,
|
||||
"hasInlineReply": false
|
||||
}
|
||||
}
|
||||
|
||||
groups[groupKey].notifications.unshift(notif)
|
||||
groups[groupKey].latestNotification = groups[groupKey].notifications[0]
|
||||
groups[groupKey].count = groups[groupKey].notifications.length
|
||||
|
||||
if (notif.notification.hasInlineReply) {
|
||||
groups[groupKey].hasInlineReply = true
|
||||
}
|
||||
}
|
||||
|
||||
return Object.values(groups).sort((a, b) => {
|
||||
return b.latestNotification.time.getTime(
|
||||
) - a.latestNotification.time.getTime()
|
||||
})
|
||||
}
|
||||
|
||||
function toggleGroupExpansion(groupKey) {
|
||||
let newExpandedGroups = {}
|
||||
for (const key in expandedGroups) {
|
||||
newExpandedGroups[key] = expandedGroups[key]
|
||||
}
|
||||
newExpandedGroups[groupKey] = !newExpandedGroups[groupKey]
|
||||
expandedGroups = newExpandedGroups
|
||||
}
|
||||
|
||||
function dismissGroup(groupKey) {
|
||||
const group = groupedNotifications.find(g => g.key === groupKey)
|
||||
if (group) {
|
||||
for (const notif of group.notifications) {
|
||||
if (notif && notif.notification) {
|
||||
notif.notification.dismiss()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const notif of allWrappers) {
|
||||
if (notif && notif.notification && getGroupKey(
|
||||
notif) === groupKey) {
|
||||
notif.notification.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function clearGroupExpansionState(groupKey) {
|
||||
let newExpandedGroups = {}
|
||||
for (const key in expandedGroups) {
|
||||
if (key !== groupKey && expandedGroups[key]) {
|
||||
newExpandedGroups[key] = true
|
||||
}
|
||||
}
|
||||
expandedGroups = newExpandedGroups
|
||||
}
|
||||
|
||||
function cleanupExpansionStates() {
|
||||
const currentGroupKeys = new Set(groupedNotifications.map(g => g.key))
|
||||
const currentMessageIds = new Set()
|
||||
for (const group of groupedNotifications) {
|
||||
for (const notif of group.notifications) {
|
||||
currentMessageIds.add(notif.notification.id)
|
||||
}
|
||||
}
|
||||
let newExpandedGroups = {}
|
||||
for (const key in expandedGroups) {
|
||||
if (currentGroupKeys.has(key) && expandedGroups[key]) {
|
||||
newExpandedGroups[key] = true
|
||||
}
|
||||
}
|
||||
expandedGroups = newExpandedGroups
|
||||
let newExpandedMessages = {}
|
||||
for (const messageId in expandedMessages) {
|
||||
if (currentMessageIds.has(messageId)
|
||||
&& expandedMessages[messageId]) {
|
||||
newExpandedMessages[messageId] = true
|
||||
}
|
||||
}
|
||||
expandedMessages = newExpandedMessages
|
||||
}
|
||||
|
||||
function toggleMessageExpansion(messageId) {
|
||||
let newExpandedMessages = {}
|
||||
for (const key in expandedMessages) {
|
||||
newExpandedMessages[key] = expandedMessages[key]
|
||||
}
|
||||
newExpandedMessages[messageId] = !newExpandedMessages[messageId]
|
||||
expandedMessages = newExpandedMessages
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: SessionData
|
||||
function onDoNotDisturbChanged() {
|
||||
if (SessionData.doNotDisturb) {
|
||||
// Hide all current popups when DND is enabled
|
||||
for (const notif of visibleNotifications) {
|
||||
notif.popup = false
|
||||
}
|
||||
visibleNotifications = []
|
||||
notificationQueue = []
|
||||
} else {
|
||||
// Re-enable popup processing when DND is disabled
|
||||
processQueue()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: typeof SettingsData !== "undefined" ? SettingsData : null
|
||||
function onUse24HourClockChanged() {
|
||||
root.clockFormatChanged = !root.clockFormatChanged
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user