mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-24 21:42:51 -05:00
notifications: improve notification center
This commit is contained in:
@@ -16,8 +16,9 @@ Singleton {
|
||||
readonly property var groupedNotifications: getGroupedNotifications()
|
||||
readonly property var groupedPopups: getGroupedPopups()
|
||||
|
||||
property var expandedGroups: ({}) // Track which groups are expanded
|
||||
property var expandedMessages: ({}) // Track which individual messages are expanded
|
||||
property var expandedGroups: ({})
|
||||
property var expandedMessages: ({})
|
||||
property bool popupsDisabled: false
|
||||
|
||||
// Notification persistence settings
|
||||
property int maxStoredNotifications: 100
|
||||
@@ -29,6 +30,7 @@ Singleton {
|
||||
|
||||
keepOnReload: false
|
||||
actionsSupported: true
|
||||
actionIconsSupported: true
|
||||
bodyHyperlinksSupported: true
|
||||
bodyImagesSupported: true
|
||||
bodyMarkupSupported: true
|
||||
@@ -36,50 +38,23 @@ Singleton {
|
||||
inlineReplySupported: true
|
||||
|
||||
onNotification: notif => {
|
||||
console.log("=== RAW NOTIFICATION DATA ===");
|
||||
console.log("appName:", notif.appName);
|
||||
console.log("summary:", notif.summary);
|
||||
console.log("body:", notif.body);
|
||||
console.log("appIcon:", notif.appIcon);
|
||||
console.log("image:", notif.image);
|
||||
console.log("urgency:", notif.urgency);
|
||||
console.log("hasInlineReply:", notif.hasInlineReply);
|
||||
console.log("=============================");
|
||||
|
||||
// Check if notification should be shown based on settings
|
||||
if (!NotificationSettings.shouldShowNotification(notif)) {
|
||||
console.log("Notification blocked by settings for app:", notif.appName);
|
||||
return;
|
||||
}
|
||||
|
||||
notif.tracked = true;
|
||||
|
||||
const wrapper = notifComponent.createObject(root, {
|
||||
popup: true,
|
||||
popup: !notif.transient, // Transient notifications show as popups but don't persist
|
||||
notification: notif
|
||||
});
|
||||
|
||||
if (wrapper) {
|
||||
const groupKey = getGroupKey(wrapper);
|
||||
console.log("New notification added to group:", groupKey, "Expansion state:", expandedGroups[groupKey] || false);
|
||||
// Handle media notification replacement
|
||||
if (wrapper.isMedia) {
|
||||
handleMediaNotification(wrapper);
|
||||
} else {
|
||||
root.notifications.push(wrapper);
|
||||
}
|
||||
|
||||
// Don't auto-expand groups - let user control expansion state
|
||||
|
||||
// Add to persistent storage (only for non-transient notifications)
|
||||
// Only add to notifications list if not transient
|
||||
if (!notif.transient) {
|
||||
root.notifications.push(wrapper);
|
||||
addToPersistentStorage(wrapper);
|
||||
}
|
||||
|
||||
console.log("Notification added. Total notifications:", root.notifications.length);
|
||||
console.log("Grouped notifications:", root.groupedNotifications.length);
|
||||
} else {
|
||||
console.error("Failed to create notification wrapper");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,7 +62,11 @@ Singleton {
|
||||
component NotifWrapper: QtObject {
|
||||
id: wrapper
|
||||
|
||||
property bool popup: true
|
||||
property bool popup: false
|
||||
|
||||
Component.onCompleted: {
|
||||
popup = !root.popupsDisabled && !notification.transient;
|
||||
}
|
||||
readonly property date time: new Date()
|
||||
readonly property string timeStr: {
|
||||
const now = new Date();
|
||||
@@ -114,6 +93,7 @@ Singleton {
|
||||
return appIcon;
|
||||
}
|
||||
readonly property string appName: notification.appName
|
||||
readonly property string desktopEntry: notification.desktopEntry
|
||||
readonly property string image: notification.image
|
||||
readonly property string cleanImage: {
|
||||
if (!image) return "";
|
||||
@@ -128,85 +108,6 @@ Singleton {
|
||||
// Enhanced properties for better handling
|
||||
readonly property bool hasImage: image && image.length > 0
|
||||
readonly property bool hasAppIcon: appIcon && appIcon.length > 0
|
||||
readonly property bool isConversation: notification.hasInlineReply
|
||||
readonly property bool isMedia: isMediaNotification()
|
||||
readonly property bool isSystem: isSystemNotification()
|
||||
|
||||
function isMediaNotification() {
|
||||
const appNameLower = appName.toLowerCase();
|
||||
const summaryLower = summary.toLowerCase();
|
||||
|
||||
// Check for media apps
|
||||
if (appNameLower.includes("spotify") ||
|
||||
appNameLower.includes("vlc") ||
|
||||
appNameLower.includes("mpv") ||
|
||||
appNameLower.includes("music") ||
|
||||
appNameLower.includes("player") ||
|
||||
appNameLower.includes("youtube") ||
|
||||
appNameLower.includes("media")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for media-related summary text
|
||||
if (summaryLower.includes("now playing") ||
|
||||
summaryLower.includes("playing") ||
|
||||
summaryLower.includes("paused") ||
|
||||
summaryLower.includes("track")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for media actions
|
||||
for (const action of actions) {
|
||||
const actionId = action.identifier.toLowerCase();
|
||||
if (actionId.includes("play") ||
|
||||
actionId.includes("pause") ||
|
||||
actionId.includes("next") ||
|
||||
actionId.includes("previous") ||
|
||||
actionId.includes("media")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function isSystemNotification() {
|
||||
const appNameLower = appName.toLowerCase();
|
||||
const summaryLower = summary.toLowerCase();
|
||||
|
||||
// Check for system apps
|
||||
if (appNameLower.includes("system") ||
|
||||
appNameLower.includes("networkmanager") ||
|
||||
appNameLower.includes("upower") ||
|
||||
appNameLower.includes("notification-daemon") ||
|
||||
appNameLower.includes("systemd") ||
|
||||
appNameLower.includes("update") ||
|
||||
appNameLower.includes("battery") ||
|
||||
appNameLower.includes("network") ||
|
||||
appNameLower.includes("wifi") ||
|
||||
appNameLower.includes("bluetooth")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for system-related summary text
|
||||
if (summaryLower.includes("battery") ||
|
||||
summaryLower.includes("power") ||
|
||||
summaryLower.includes("update") ||
|
||||
summaryLower.includes("connected") ||
|
||||
summaryLower.includes("disconnected") ||
|
||||
summaryLower.includes("network") ||
|
||||
summaryLower.includes("wifi") ||
|
||||
summaryLower.includes("bluetooth")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
readonly property Connections conn: Connections {
|
||||
target: wrapper.notification.Retainable
|
||||
@@ -218,11 +119,14 @@ Singleton {
|
||||
const groupKey = getGroupKey(wrapper);
|
||||
root.notifications.splice(index, 1);
|
||||
|
||||
// Check if this group now has no notifications left
|
||||
// Check if this group now has no notifications left or only 1 left
|
||||
const remainingInGroup = root.notifications.filter(n => getGroupKey(n) === groupKey);
|
||||
if (remainingInGroup.length === 0) {
|
||||
// Immediately clear expansion state for empty group
|
||||
clearGroupExpansionState(groupKey);
|
||||
} else if (remainingInGroup.length === 1) {
|
||||
// Collapse groups that only have 1 notification left
|
||||
clearGroupExpansionState(groupKey);
|
||||
}
|
||||
|
||||
// Clean up all expansion states
|
||||
@@ -243,88 +147,43 @@ Singleton {
|
||||
|
||||
// Helper functions
|
||||
function clearAllNotifications() {
|
||||
// Create a copy of the array to avoid modification during iteration
|
||||
// Actually dismiss all notifications from center
|
||||
const notificationsCopy = [...root.notifications];
|
||||
for (const notif of notificationsCopy) {
|
||||
notificationsCopy.forEach(notif => {
|
||||
notif.notification.dismiss();
|
||||
}
|
||||
// Note: Expansion states will be cleaned up by onDropped as notifications are removed
|
||||
});
|
||||
// Clear all expansion states
|
||||
expandedGroups = {};
|
||||
expandedMessages = {};
|
||||
}
|
||||
|
||||
function dismissNotification(wrapper) {
|
||||
wrapper.notification.dismiss();
|
||||
}
|
||||
|
||||
function handleMediaNotification(newMediaWrapper) {
|
||||
const groupKey = getGroupKey(newMediaWrapper);
|
||||
|
||||
// Find and replace any existing media notification from the same app
|
||||
for (let i = notifications.length - 1; i >= 0; i--) {
|
||||
const existing = notifications[i];
|
||||
if (existing.isMedia && getGroupKey(existing) === groupKey) {
|
||||
// Replace the existing media notification
|
||||
existing.notification.dismiss();
|
||||
break;
|
||||
|
||||
function hidePopup(wrapper) {
|
||||
wrapper.popup = false;
|
||||
}
|
||||
|
||||
function disablePopups(disable) {
|
||||
popupsDisabled = disable;
|
||||
if (disable) {
|
||||
for (const notif of root.notifications) {
|
||||
notif.popup = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the new media notification
|
||||
root.notifications.push(newMediaWrapper);
|
||||
}
|
||||
|
||||
|
||||
// Android 16-style notification grouping functions
|
||||
function getGroupKey(wrapper) {
|
||||
const appName = wrapper.appName.toLowerCase();
|
||||
|
||||
// Media notifications: replace previous media notification from same app
|
||||
if (wrapper.isMedia) {
|
||||
return `${appName}:media`;
|
||||
// Priority 1: Use desktopEntry if available
|
||||
if (wrapper.desktopEntry && wrapper.desktopEntry !== "") {
|
||||
return wrapper.desktopEntry.toLowerCase();
|
||||
}
|
||||
|
||||
// System notifications: group by category
|
||||
if (wrapper.isSystem) {
|
||||
const summary = wrapper.summary.toLowerCase();
|
||||
|
||||
if (summary.includes("battery") || summary.includes("power")) {
|
||||
return "system:battery";
|
||||
}
|
||||
if (summary.includes("network") || summary.includes("wifi") || summary.includes("connected") || summary.includes("disconnected")) {
|
||||
return "system:network";
|
||||
}
|
||||
if (summary.includes("update") || summary.includes("upgrade")) {
|
||||
return "system:updates";
|
||||
}
|
||||
if (summary.includes("bluetooth")) {
|
||||
return "system:bluetooth";
|
||||
}
|
||||
|
||||
// Default system grouping
|
||||
return "system:general";
|
||||
}
|
||||
|
||||
// Conversation apps with inline reply
|
||||
if (wrapper.isConversation) {
|
||||
const summary = wrapper.summary.toLowerCase();
|
||||
|
||||
// Group by conversation/channel name from summary
|
||||
if (summary.includes("#")) {
|
||||
const channelMatch = summary.match(/#[\w-]+/);
|
||||
if (channelMatch) {
|
||||
return `${appName}:${channelMatch[0]}`;
|
||||
}
|
||||
}
|
||||
|
||||
// Group by sender/conversation name if meaningful
|
||||
if (summary && !summary.includes("new message") && !summary.includes("notification")) {
|
||||
return `${appName}:${summary}`;
|
||||
}
|
||||
|
||||
// Default conversation grouping
|
||||
return `${appName}:conversation`;
|
||||
}
|
||||
|
||||
// Default: Group by app
|
||||
return appName;
|
||||
// Priority 2: Use appName as fallback
|
||||
return wrapper.appName.toLowerCase();
|
||||
}
|
||||
|
||||
function getGroupedNotifications() {
|
||||
@@ -340,9 +199,6 @@ Singleton {
|
||||
latestNotification: null,
|
||||
count: 0,
|
||||
hasInlineReply: false,
|
||||
isConversation: notif.isConversation,
|
||||
isMedia: notif.isMedia,
|
||||
isSystem: notif.isSystem
|
||||
};
|
||||
}
|
||||
|
||||
@@ -356,6 +212,11 @@ Singleton {
|
||||
}
|
||||
|
||||
return Object.values(groups).sort((a, b) => {
|
||||
const aUrgency = a.latestNotification.urgency || 0;
|
||||
const bUrgency = b.latestNotification.urgency || 0;
|
||||
if (aUrgency !== bUrgency) {
|
||||
return bUrgency - aUrgency;
|
||||
}
|
||||
return b.latestNotification.time.getTime() - a.latestNotification.time.getTime();
|
||||
});
|
||||
}
|
||||
@@ -373,9 +234,6 @@ Singleton {
|
||||
latestNotification: null,
|
||||
count: 0,
|
||||
hasInlineReply: false,
|
||||
isConversation: notif.isConversation,
|
||||
isMedia: notif.isMedia,
|
||||
isSystem: notif.isSystem
|
||||
};
|
||||
}
|
||||
|
||||
@@ -389,6 +247,11 @@ Singleton {
|
||||
}
|
||||
|
||||
return Object.values(groups).sort((a, b) => {
|
||||
const aUrgency = a.latestNotification.urgency || 0;
|
||||
const bUrgency = b.latestNotification.urgency || 0;
|
||||
if (aUrgency !== bUrgency) {
|
||||
return bUrgency - aUrgency;
|
||||
}
|
||||
return b.latestNotification.time.getTime() - a.latestNotification.time.getTime();
|
||||
});
|
||||
}
|
||||
@@ -403,18 +266,15 @@ Singleton {
|
||||
}
|
||||
|
||||
function dismissGroup(groupKey) {
|
||||
console.log("Completely dismissing group:", groupKey);
|
||||
const group = groupedNotifications.find(g => g.key === groupKey);
|
||||
if (group) {
|
||||
for (const notif of group.notifications) {
|
||||
notif.notification.dismiss();
|
||||
}
|
||||
}
|
||||
// Note: Expansion state will be cleaned up by onDropped when notifications are removed
|
||||
}
|
||||
|
||||
function clearGroupExpansionState(groupKey) {
|
||||
// Immediately remove expansion state for a specific group
|
||||
let newExpandedGroups = {};
|
||||
for (const key in expandedGroups) {
|
||||
if (key !== groupKey && expandedGroups[key]) {
|
||||
@@ -422,22 +282,16 @@ Singleton {
|
||||
}
|
||||
}
|
||||
expandedGroups = newExpandedGroups;
|
||||
|
||||
console.log("Cleared expansion state for group:", groupKey);
|
||||
}
|
||||
|
||||
function cleanupExpansionStates() {
|
||||
// Get all current group keys and message IDs
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up expanded groups that no longer exist
|
||||
let newExpandedGroups = {};
|
||||
for (const key in expandedGroups) {
|
||||
if (currentGroupKeys.has(key) && expandedGroups[key]) {
|
||||
@@ -445,8 +299,6 @@ Singleton {
|
||||
}
|
||||
}
|
||||
expandedGroups = newExpandedGroups;
|
||||
|
||||
// Clean up expanded messages that no longer exist
|
||||
let newExpandedMessages = {};
|
||||
for (const messageId in expandedMessages) {
|
||||
if (currentMessageIds.has(messageId) && expandedMessages[messageId]) {
|
||||
@@ -469,69 +321,15 @@ Singleton {
|
||||
if (group.count === 1) {
|
||||
return group.latestNotification.summary;
|
||||
}
|
||||
|
||||
if (group.isMedia) {
|
||||
return "Now Playing";
|
||||
}
|
||||
|
||||
if (group.isSystem) {
|
||||
const keyParts = group.key.split(":");
|
||||
if (keyParts.length > 1) {
|
||||
const systemCategory = keyParts[1];
|
||||
switch (systemCategory) {
|
||||
case "battery": return `${group.count} Battery alerts`;
|
||||
case "network": return `${group.count} Network updates`;
|
||||
case "updates": return `${group.count} System updates`;
|
||||
case "bluetooth": return `${group.count} Bluetooth updates`;
|
||||
default: return `${group.count} System notifications`;
|
||||
}
|
||||
}
|
||||
return `${group.count} System notifications`;
|
||||
}
|
||||
|
||||
if (group.isConversation) {
|
||||
const keyParts = group.key.split(":");
|
||||
if (keyParts.length > 1) {
|
||||
const conversationKey = keyParts[keyParts.length - 1];
|
||||
if (conversationKey !== "conversation") {
|
||||
return `${conversationKey}: ${group.count} messages`;
|
||||
}
|
||||
}
|
||||
return `${group.count} new messages`;
|
||||
}
|
||||
|
||||
return `${group.count} notifications`;
|
||||
}
|
||||
|
||||
function getGroupBody(group) {
|
||||
if (group.count === 1) {
|
||||
return group.latestNotification.body;
|
||||
}
|
||||
|
||||
if (group.isMedia) {
|
||||
const latest = group.latestNotification;
|
||||
if (latest.body && latest.body.length > 0) {
|
||||
return latest.body;
|
||||
}
|
||||
return latest.summary;
|
||||
}
|
||||
|
||||
if (group.isSystem) {
|
||||
return `Latest: ${group.latestNotification.summary}`;
|
||||
}
|
||||
|
||||
if (group.isConversation) {
|
||||
const latest = group.latestNotification;
|
||||
if (latest.body && latest.body.length > 0) {
|
||||
return latest.body;
|
||||
}
|
||||
return "Tap to view conversation";
|
||||
}
|
||||
|
||||
return `Latest: ${group.latestNotification.summary}`;
|
||||
}
|
||||
|
||||
// Notification persistence functions
|
||||
function addToPersistentStorage(wrapper) {
|
||||
const persistedNotif = {
|
||||
id: wrapper.notification.id,
|
||||
@@ -542,45 +340,29 @@ Singleton {
|
||||
image: wrapper.image,
|
||||
urgency: wrapper.urgency,
|
||||
timestamp: wrapper.time.getTime(),
|
||||
isConversation: wrapper.isConversation,
|
||||
isMedia: wrapper.isMedia,
|
||||
isSystem: wrapper.isSystem
|
||||
};
|
||||
|
||||
// Add to beginning of array
|
||||
persistedNotifications.unshift(persistedNotif);
|
||||
|
||||
// Clean up old notifications
|
||||
cleanupPersistentStorage();
|
||||
}
|
||||
|
||||
function cleanupPersistentStorage() {
|
||||
const now = new Date().getTime();
|
||||
let newPersisted = [];
|
||||
|
||||
for (let i = 0; i < persistedNotifications.length && i < maxStoredNotifications; i++) {
|
||||
const notif = persistedNotifications[i];
|
||||
if (now - notif.timestamp < maxNotificationAge) {
|
||||
newPersisted.push(notif);
|
||||
}
|
||||
}
|
||||
|
||||
persistedNotifications = newPersisted;
|
||||
}
|
||||
|
||||
function getPersistentNotificationsByApp(appName) {
|
||||
return persistedNotifications.filter(notif => notif.appName.toLowerCase() === appName.toLowerCase());
|
||||
}
|
||||
|
||||
function getPersistentNotificationsByType(type) {
|
||||
switch (type) {
|
||||
case "conversation": return persistedNotifications.filter(notif => notif.isConversation);
|
||||
case "media": return persistedNotifications.filter(notif => notif.isMedia);
|
||||
case "system": return persistedNotifications.filter(notif => notif.isSystem);
|
||||
default: return persistedNotifications;
|
||||
}
|
||||
return persistedNotifications;
|
||||
}
|
||||
|
||||
function searchPersistentNotifications(query) {
|
||||
const searchLower = query.toLowerCase();
|
||||
return persistedNotifications.filter(notif =>
|
||||
@@ -589,8 +371,6 @@ Singleton {
|
||||
notif.body.toLowerCase().includes(searchLower)
|
||||
);
|
||||
}
|
||||
|
||||
// Initialize persistence on component creation
|
||||
Component.onCompleted: {
|
||||
cleanupPersistentStorage();
|
||||
}
|
||||
|
||||
@@ -1,194 +0,0 @@
|
||||
pragma Singleton
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
// General notification settings
|
||||
property bool notificationsEnabled: true
|
||||
property bool soundEnabled: true
|
||||
property bool persistNotifications: true
|
||||
property int defaultTimeout: 5000 // milliseconds
|
||||
|
||||
// Grouping settings
|
||||
property bool enableSmartGrouping: true
|
||||
property bool autoExpandConversations: true
|
||||
property bool replaceMediaNotifications: true
|
||||
|
||||
// Persistence settings
|
||||
property int maxStoredNotifications: 100
|
||||
property int notificationRetentionDays: 7
|
||||
|
||||
// Display settings
|
||||
property bool showNotificationPopups: true
|
||||
property bool showAppIcons: true
|
||||
property bool showTimestamps: true
|
||||
property bool enableInlineReply: true
|
||||
property bool showActionButtons: true
|
||||
|
||||
// Priority settings
|
||||
property bool allowCriticalNotifications: true
|
||||
property bool respectDoNotDisturb: true
|
||||
|
||||
// App-specific settings
|
||||
property var appSettings: ({})
|
||||
|
||||
// Do Not Disturb settings
|
||||
property bool doNotDisturbMode: false
|
||||
property string doNotDisturbStart: "22:00"
|
||||
property string doNotDisturbEnd: "08:00"
|
||||
property bool allowCriticalInDND: true
|
||||
|
||||
// Sound settings
|
||||
property string notificationSound: "default"
|
||||
property real soundVolume: 0.7
|
||||
property bool vibrationEnabled: false
|
||||
|
||||
function getAppSetting(appName, setting, defaultValue) {
|
||||
const app = appSettings[appName.toLowerCase()];
|
||||
if (app && app.hasOwnProperty(setting)) {
|
||||
return app[setting];
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
function setAppSetting(appName, setting, value) {
|
||||
let newAppSettings = {};
|
||||
for (const app in appSettings) {
|
||||
newAppSettings[app] = appSettings[app];
|
||||
}
|
||||
|
||||
const appKey = appName.toLowerCase();
|
||||
if (!newAppSettings[appKey]) {
|
||||
newAppSettings[appKey] = {};
|
||||
}
|
||||
newAppSettings[appKey][setting] = value;
|
||||
appSettings = newAppSettings;
|
||||
|
||||
// Save to persistent storage
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
function isAppBlocked(appName) {
|
||||
const appKey = appName.toLowerCase();
|
||||
if (appKey === "notify-send" || appKey === "libnotify") {
|
||||
return false;
|
||||
}
|
||||
return getAppSetting(appName, "blocked", false);
|
||||
}
|
||||
|
||||
function isAppMuted(appName) {
|
||||
return getAppSetting(appName, "muted", false);
|
||||
}
|
||||
|
||||
function getAppTimeout(appName) {
|
||||
return getAppSetting(appName, "timeout", defaultTimeout);
|
||||
}
|
||||
|
||||
function isInDoNotDisturbMode() {
|
||||
if (!doNotDisturbMode && !respectDoNotDisturb) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const now = new Date();
|
||||
const currentTime = now.getHours() * 60 + now.getMinutes();
|
||||
|
||||
const startParts = doNotDisturbStart.split(":");
|
||||
const endParts = doNotDisturbEnd.split(":");
|
||||
const startTime = parseInt(startParts[0]) * 60 + parseInt(startParts[1]);
|
||||
const endTime = parseInt(endParts[0]) * 60 + parseInt(endParts[1]);
|
||||
|
||||
if (startTime <= endTime) {
|
||||
// Same day range (e.g., 9:00 - 17:00)
|
||||
return currentTime >= startTime && currentTime <= endTime;
|
||||
} else {
|
||||
// Overnight range (e.g., 22:00 - 08:00)
|
||||
return currentTime >= startTime || currentTime <= endTime;
|
||||
}
|
||||
}
|
||||
|
||||
function shouldShowNotification(notification) {
|
||||
// Check if notifications are globally disabled
|
||||
if (!notificationsEnabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if app is blocked
|
||||
if (isAppBlocked(notification.appName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// DND logic temporarily disabled for all notifications
|
||||
// if (isInDoNotDisturbMode()) {
|
||||
// // Allow critical notifications if configured
|
||||
// if (allowCriticalInDND && notification.urgency === 2) {
|
||||
// return true;
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function shouldPlaySound(notification) {
|
||||
if (!soundEnabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isAppMuted(notification.appName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isInDoNotDisturbMode() && !allowCriticalInDND) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function saveSettings() {
|
||||
// In a real implementation, this would save to a config file
|
||||
console.log("NotificationSettings: Settings saved");
|
||||
}
|
||||
|
||||
function loadSettings() {
|
||||
// In a real implementation, this would load from a config file
|
||||
console.log("NotificationSettings: Settings loaded");
|
||||
}
|
||||
|
||||
function resetToDefaults() {
|
||||
notificationsEnabled = true;
|
||||
soundEnabled = true;
|
||||
persistNotifications = true;
|
||||
defaultTimeout = 5000;
|
||||
enableSmartGrouping = true;
|
||||
autoExpandConversations = true;
|
||||
replaceMediaNotifications = true;
|
||||
maxStoredNotifications = 100;
|
||||
notificationRetentionDays = 7;
|
||||
showNotificationPopups = true;
|
||||
showAppIcons = true;
|
||||
showTimestamps = true;
|
||||
enableInlineReply = true;
|
||||
showActionButtons = true;
|
||||
allowCriticalNotifications = true;
|
||||
respectDoNotDisturb = true;
|
||||
doNotDisturbMode = false;
|
||||
doNotDisturbStart = "22:00";
|
||||
doNotDisturbEnd = "08:00";
|
||||
allowCriticalInDND = true;
|
||||
notificationSound = "default";
|
||||
soundVolume = 0.7;
|
||||
vibrationEnabled = false;
|
||||
appSettings = {};
|
||||
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
loadSettings();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user