mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-24 13:32:50 -05:00
settings: optimize mem usage
- keep un-loaded unless called upon
This commit is contained in:
@@ -360,11 +360,33 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsModal {
|
LazyLoader {
|
||||||
id: settingsModal
|
id: settingsModalLoader
|
||||||
|
|
||||||
|
active: false
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
PopoutService.settingsModal = settingsModal;
|
PopoutService.settingsModalLoader = settingsModalLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
onActiveChanged: {
|
||||||
|
if (active && item) {
|
||||||
|
PopoutService.settingsModal = item;
|
||||||
|
PopoutService._onSettingsModalLoaded();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsModal {
|
||||||
|
id: settingsModal
|
||||||
|
property bool wasShown: false
|
||||||
|
|
||||||
|
onVisibleChanged: {
|
||||||
|
if (visible) {
|
||||||
|
wasShown = true;
|
||||||
|
} else if (wasShown) {
|
||||||
|
PopoutService.unloadSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -534,7 +556,6 @@ Item {
|
|||||||
hyprKeybindsModalLoader: hyprKeybindsModalLoader
|
hyprKeybindsModalLoader: hyprKeybindsModalLoader
|
||||||
dankBarRepeater: dankBarRepeater
|
dankBarRepeater: dankBarRepeater
|
||||||
hyprlandOverviewLoader: hyprlandOverviewLoader
|
hyprlandOverviewLoader: hyprlandOverviewLoader
|
||||||
settingsModal: settingsModal
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Variants {
|
Variants {
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ Item {
|
|||||||
required property var hyprKeybindsModalLoader
|
required property var hyprKeybindsModalLoader
|
||||||
required property var dankBarRepeater
|
required property var dankBarRepeater
|
||||||
required property var hyprlandOverviewLoader
|
required property var hyprlandOverviewLoader
|
||||||
required property var settingsModal
|
|
||||||
|
|
||||||
function getFirstBar() {
|
function getFirstBar() {
|
||||||
if (!root.dankBarRepeater || root.dankBarRepeater.count === 0)
|
if (!root.dankBarRepeater || root.dankBarRepeater.count === 0)
|
||||||
@@ -533,17 +532,17 @@ Item {
|
|||||||
|
|
||||||
IpcHandler {
|
IpcHandler {
|
||||||
function open(): string {
|
function open(): string {
|
||||||
root.settingsModal.show();
|
PopoutService.openSettings();
|
||||||
return "SETTINGS_OPEN_SUCCESS";
|
return "SETTINGS_OPEN_SUCCESS";
|
||||||
}
|
}
|
||||||
|
|
||||||
function close(): string {
|
function close(): string {
|
||||||
root.settingsModal.hide();
|
PopoutService.closeSettings();
|
||||||
return "SETTINGS_CLOSE_SUCCESS";
|
return "SETTINGS_CLOSE_SUCCESS";
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggle(): string {
|
function toggle(): string {
|
||||||
root.settingsModal.toggle();
|
PopoutService.toggleSettings();
|
||||||
return "SETTINGS_TOGGLE_SUCCESS";
|
return "SETTINGS_TOGGLE_SUCCESS";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -552,12 +551,17 @@ Item {
|
|||||||
|
|
||||||
IpcHandler {
|
IpcHandler {
|
||||||
function browse(type: string) {
|
function browse(type: string) {
|
||||||
if (type === "wallpaper") {
|
const modal = PopoutService.settingsModal;
|
||||||
root.settingsModal.wallpaperBrowser.allowStacking = false;
|
if (modal) {
|
||||||
root.settingsModal.wallpaperBrowser.open();
|
if (type === "wallpaper") {
|
||||||
} else if (type === "profile") {
|
modal.wallpaperBrowser.allowStacking = false;
|
||||||
root.settingsModal.profileBrowser.allowStacking = false;
|
modal.wallpaperBrowser.open();
|
||||||
root.settingsModal.profileBrowser.open();
|
} else if (type === "profile") {
|
||||||
|
modal.profileBrowser.allowStacking = false;
|
||||||
|
modal.profileBrowser.open();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PopoutService.openSettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -160,6 +160,7 @@ Variants {
|
|||||||
asynchronous: true
|
asynchronous: true
|
||||||
smooth: true
|
smooth: true
|
||||||
cache: true
|
cache: true
|
||||||
|
sourceSize: Qt.size(modelData.width, modelData.height)
|
||||||
fillMode: root.getFillMode(SessionData.isGreeterMode ? GreetdSettings.wallpaperFillMode : SettingsData.wallpaperFillMode)
|
fillMode: root.getFillMode(SessionData.isGreeterMode ? GreetdSettings.wallpaperFillMode : SettingsData.wallpaperFillMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,6 +172,7 @@ Variants {
|
|||||||
asynchronous: true
|
asynchronous: true
|
||||||
smooth: true
|
smooth: true
|
||||||
cache: true
|
cache: true
|
||||||
|
sourceSize: Qt.size(modelData.width, modelData.height)
|
||||||
fillMode: root.getFillMode(SessionData.isGreeterMode ? GreetdSettings.wallpaperFillMode : SettingsData.wallpaperFillMode)
|
fillMode: root.getFillMode(SessionData.isGreeterMode ? GreetdSettings.wallpaperFillMode : SettingsData.wallpaperFillMode)
|
||||||
|
|
||||||
onStatusChanged: {
|
onStatusChanged: {
|
||||||
@@ -218,14 +220,16 @@ Variants {
|
|||||||
duration: 1000
|
duration: 1000
|
||||||
easing.type: Easing.InOutCubic
|
easing.type: Easing.InOutCubic
|
||||||
onFinished: {
|
onFinished: {
|
||||||
|
const tempSource = nextWallpaper.source;
|
||||||
|
if (tempSource && nextWallpaper.status === Image.Ready && !tempSource.toString().startsWith("#")) {
|
||||||
|
currentWallpaper.source = tempSource;
|
||||||
|
}
|
||||||
|
root.transitionProgress = 0.0;
|
||||||
|
currentWallpaper.opacity = 1;
|
||||||
|
nextWallpaper.opacity = 0;
|
||||||
|
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
if (nextWallpaper.source && nextWallpaper.status === Image.Ready && !nextWallpaper.source.toString().startsWith("#")) {
|
|
||||||
currentWallpaper.source = nextWallpaper.source;
|
|
||||||
}
|
|
||||||
nextWallpaper.source = "";
|
nextWallpaper.source = "";
|
||||||
currentWallpaper.opacity = 1;
|
|
||||||
nextWallpaper.opacity = 0;
|
|
||||||
root.transitionProgress = 0.0;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ Rectangle {
|
|||||||
backgroundColor: "transparent"
|
backgroundColor: "transparent"
|
||||||
onClicked: {
|
onClicked: {
|
||||||
root.settingsButtonClicked();
|
root.settingsButtonClicked();
|
||||||
settingsModal.show();
|
PopoutService.openSettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -301,7 +301,7 @@ DankPopout {
|
|||||||
let settingsIndex = SettingsData.weatherEnabled ? 4 : 3;
|
let settingsIndex = SettingsData.weatherEnabled ? 4 : 3;
|
||||||
if (index === settingsIndex) {
|
if (index === settingsIndex) {
|
||||||
dashVisible = false;
|
dashVisible = false;
|
||||||
settingsModal.show();
|
PopoutService.openSettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,19 +2,16 @@ import QtQuick
|
|||||||
import QtQuick.Effects
|
import QtQuick.Effects
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import Quickshell.Widgets
|
|
||||||
import Quickshell.Io
|
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
import qs.Modules
|
|
||||||
import qs.Services
|
import qs.Services
|
||||||
|
|
||||||
Variants {
|
Variants {
|
||||||
model: {
|
model: {
|
||||||
if (SessionData.isGreeterMode) {
|
if (SessionData.isGreeterMode) {
|
||||||
return Quickshell.screens
|
return Quickshell.screens;
|
||||||
}
|
}
|
||||||
return SettingsData.getFilteredScreens("wallpaper")
|
return SettingsData.getFilteredScreens("wallpaper");
|
||||||
}
|
}
|
||||||
|
|
||||||
PanelWindow {
|
PanelWindow {
|
||||||
@@ -52,9 +49,9 @@ Variants {
|
|||||||
target: SessionData
|
target: SessionData
|
||||||
function onIsLightModeChanged() {
|
function onIsLightModeChanged() {
|
||||||
if (SessionData.perModeWallpaper) {
|
if (SessionData.perModeWallpaper) {
|
||||||
var newSource = SessionData.getMonitorWallpaper(modelData.name) || ""
|
var newSource = SessionData.getMonitorWallpaper(modelData.name) || "";
|
||||||
if (newSource !== root.source) {
|
if (newSource !== root.source) {
|
||||||
root.source = newSource
|
root.source = newSource;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -62,19 +59,19 @@ Variants {
|
|||||||
onTransitionTypeChanged: {
|
onTransitionTypeChanged: {
|
||||||
if (transitionType === "random") {
|
if (transitionType === "random") {
|
||||||
if (SessionData.includedTransitions.length === 0) {
|
if (SessionData.includedTransitions.length === 0) {
|
||||||
actualTransitionType = "none"
|
actualTransitionType = "none";
|
||||||
} else {
|
} else {
|
||||||
actualTransitionType = SessionData.includedTransitions[Math.floor(Math.random() * SessionData.includedTransitions.length)]
|
actualTransitionType = SessionData.includedTransitions[Math.floor(Math.random() * SessionData.includedTransitions.length)];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
actualTransitionType = transitionType
|
actualTransitionType = transitionType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onActualTransitionTypeChanged: {
|
onActualTransitionTypeChanged: {
|
||||||
if (actualTransitionType === "none") {
|
if (actualTransitionType === "none") {
|
||||||
currentWallpaper.visible = true
|
currentWallpaper.visible = true;
|
||||||
nextWallpaper.visible = false
|
nextWallpaper.visible = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
property real transitionProgress: 0
|
property real transitionProgress: 0
|
||||||
@@ -94,103 +91,110 @@ Variants {
|
|||||||
property bool booting: !hasCurrent && nextWallpaper.status === Image.Ready
|
property bool booting: !hasCurrent && nextWallpaper.status === Image.Ready
|
||||||
|
|
||||||
function getFillMode(modeName) {
|
function getFillMode(modeName) {
|
||||||
switch(modeName) {
|
switch (modeName) {
|
||||||
case "Stretch": return Image.Stretch
|
case "Stretch":
|
||||||
case "Fit":
|
return Image.Stretch;
|
||||||
case "PreserveAspectFit": return Image.PreserveAspectFit
|
case "Fit":
|
||||||
case "Fill":
|
case "PreserveAspectFit":
|
||||||
case "PreserveAspectCrop": return Image.PreserveAspectCrop
|
return Image.PreserveAspectFit;
|
||||||
case "Tile": return Image.Tile
|
case "Fill":
|
||||||
case "TileVertically": return Image.TileVertically
|
case "PreserveAspectCrop":
|
||||||
case "TileHorizontally": return Image.TileHorizontally
|
return Image.PreserveAspectCrop;
|
||||||
case "Pad": return Image.Pad
|
case "Tile":
|
||||||
default: return Image.PreserveAspectCrop
|
return Image.Tile;
|
||||||
|
case "TileVertically":
|
||||||
|
return Image.TileVertically;
|
||||||
|
case "TileHorizontally":
|
||||||
|
return Image.TileHorizontally;
|
||||||
|
case "Pad":
|
||||||
|
return Image.Pad;
|
||||||
|
default:
|
||||||
|
return Image.PreserveAspectCrop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
if (source) {
|
if (source) {
|
||||||
const formattedSource = source.startsWith("file://") ? source : "file://" + source
|
const formattedSource = source.startsWith("file://") ? source : "file://" + source;
|
||||||
setWallpaperImmediate(formattedSource)
|
setWallpaperImmediate(formattedSource);
|
||||||
}
|
}
|
||||||
isInitialized = true
|
isInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
onSourceChanged: {
|
onSourceChanged: {
|
||||||
const isColor = source.startsWith("#")
|
const isColor = source.startsWith("#");
|
||||||
|
|
||||||
if (!source) {
|
if (!source) {
|
||||||
setWallpaperImmediate("")
|
setWallpaperImmediate("");
|
||||||
} else if (isColor) {
|
} else if (isColor) {
|
||||||
setWallpaperImmediate("")
|
setWallpaperImmediate("");
|
||||||
} else {
|
} else {
|
||||||
if (!isInitialized || !currentWallpaper.source) {
|
if (!isInitialized || !currentWallpaper.source) {
|
||||||
setWallpaperImmediate(source.startsWith("file://") ? source : "file://" + source)
|
setWallpaperImmediate(source.startsWith("file://") ? source : "file://" + source);
|
||||||
isInitialized = true
|
isInitialized = true;
|
||||||
} else if (CompositorService.isNiri && SessionData.isSwitchingMode) {
|
} else if (CompositorService.isNiri && SessionData.isSwitchingMode) {
|
||||||
setWallpaperImmediate(source.startsWith("file://") ? source : "file://" + source)
|
setWallpaperImmediate(source.startsWith("file://") ? source : "file://" + source);
|
||||||
} else {
|
} else {
|
||||||
changeWallpaper(source.startsWith("file://") ? source : "file://" + source)
|
changeWallpaper(source.startsWith("file://") ? source : "file://" + source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setWallpaperImmediate(newSource) {
|
function setWallpaperImmediate(newSource) {
|
||||||
transitionAnimation.stop()
|
transitionAnimation.stop();
|
||||||
root.transitionProgress = 0.0
|
root.transitionProgress = 0.0;
|
||||||
currentWallpaper.source = newSource
|
currentWallpaper.source = newSource;
|
||||||
nextWallpaper.source = ""
|
nextWallpaper.source = "";
|
||||||
currentWallpaper.visible = true
|
currentWallpaper.visible = true;
|
||||||
nextWallpaper.visible = false
|
nextWallpaper.visible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeWallpaper(newPath, force) {
|
function changeWallpaper(newPath, force) {
|
||||||
if (!force && newPath === currentWallpaper.source)
|
if (!force && newPath === currentWallpaper.source)
|
||||||
return
|
return;
|
||||||
if (!newPath || newPath.startsWith("#"))
|
if (!newPath || newPath.startsWith("#"))
|
||||||
return
|
return;
|
||||||
|
|
||||||
if (root.transitioning) {
|
if (root.transitioning) {
|
||||||
transitionAnimation.stop()
|
transitionAnimation.stop();
|
||||||
root.transitionProgress = 0
|
root.transitionProgress = 0;
|
||||||
currentWallpaper.source = nextWallpaper.source
|
currentWallpaper.source = nextWallpaper.source;
|
||||||
nextWallpaper.source = ""
|
nextWallpaper.source = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no current wallpaper, set immediately to avoid scaling issues
|
// If no current wallpaper, set immediately to avoid scaling issues
|
||||||
if (!currentWallpaper.source) {
|
if (!currentWallpaper.source) {
|
||||||
setWallpaperImmediate(newPath)
|
setWallpaperImmediate(newPath);
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If transition is "none", set immediately
|
// If transition is "none", set immediately
|
||||||
if (root.transitionType === "random") {
|
if (root.transitionType === "random") {
|
||||||
if (SessionData.includedTransitions.length === 0) {
|
if (SessionData.includedTransitions.length === 0) {
|
||||||
root.actualTransitionType = "none"
|
root.actualTransitionType = "none";
|
||||||
} else {
|
} else {
|
||||||
root.actualTransitionType = SessionData.includedTransitions[Math.floor(Math.random() * SessionData.includedTransitions.length)]
|
root.actualTransitionType = SessionData.includedTransitions[Math.floor(Math.random() * SessionData.includedTransitions.length)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root.actualTransitionType === "none") {
|
if (root.actualTransitionType === "none") {
|
||||||
setWallpaperImmediate(newPath)
|
setWallpaperImmediate(newPath);
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root.actualTransitionType === "wipe") {
|
if (root.actualTransitionType === "wipe") {
|
||||||
root.wipeDirection = Math.random() * 4
|
root.wipeDirection = Math.random() * 4;
|
||||||
} else if (root.actualTransitionType === "disc") {
|
} else if (root.actualTransitionType === "disc") {
|
||||||
root.discCenterX = Math.random()
|
root.discCenterX = Math.random();
|
||||||
root.discCenterY = Math.random()
|
root.discCenterY = Math.random();
|
||||||
} else if (root.actualTransitionType === "stripes") {
|
} else if (root.actualTransitionType === "stripes") {
|
||||||
root.stripesCount = Math.round(Math.random() * 20 + 4)
|
root.stripesCount = Math.round(Math.random() * 20 + 4);
|
||||||
root.stripesAngle = Math.random() * 360
|
root.stripesAngle = Math.random() * 360;
|
||||||
}
|
}
|
||||||
|
|
||||||
nextWallpaper.source = newPath
|
nextWallpaper.source = newPath;
|
||||||
|
|
||||||
if (nextWallpaper.status === Image.Ready) {
|
if (nextWallpaper.status === Image.Ready) {
|
||||||
transitionAnimation.start()
|
transitionAnimation.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,6 +231,7 @@ Variants {
|
|||||||
asynchronous: true
|
asynchronous: true
|
||||||
smooth: true
|
smooth: true
|
||||||
cache: true
|
cache: true
|
||||||
|
sourceSize: Qt.size(modelData.width, modelData.height)
|
||||||
fillMode: root.getFillMode(SettingsData.wallpaperFillMode)
|
fillMode: root.getFillMode(SettingsData.wallpaperFillMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,20 +244,20 @@ Variants {
|
|||||||
asynchronous: true
|
asynchronous: true
|
||||||
smooth: true
|
smooth: true
|
||||||
cache: true
|
cache: true
|
||||||
|
sourceSize: Qt.size(modelData.width, modelData.height)
|
||||||
fillMode: root.getFillMode(SettingsData.wallpaperFillMode)
|
fillMode: root.getFillMode(SettingsData.wallpaperFillMode)
|
||||||
|
|
||||||
onStatusChanged: {
|
onStatusChanged: {
|
||||||
if (status !== Image.Ready)
|
if (status !== Image.Ready)
|
||||||
return
|
return;
|
||||||
|
|
||||||
if (root.actualTransitionType === "none") {
|
if (root.actualTransitionType === "none") {
|
||||||
currentWallpaper.source = source
|
currentWallpaper.source = source;
|
||||||
nextWallpaper.source = ""
|
nextWallpaper.source = "";
|
||||||
root.transitionProgress = 0.0
|
root.transitionProgress = 0.0;
|
||||||
} else {
|
} else {
|
||||||
visible = true
|
visible = true;
|
||||||
if (!root.transitioning) {
|
if (!root.transitioning) {
|
||||||
transitionAnimation.start()
|
transitionAnimation.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -265,21 +270,21 @@ Variants {
|
|||||||
sourceComponent: {
|
sourceComponent: {
|
||||||
switch (root.actualTransitionType) {
|
switch (root.actualTransitionType) {
|
||||||
case "fade":
|
case "fade":
|
||||||
return fadeComp
|
return fadeComp;
|
||||||
case "wipe":
|
case "wipe":
|
||||||
return wipeComp
|
return wipeComp;
|
||||||
case "disc":
|
case "disc":
|
||||||
return discComp
|
return discComp;
|
||||||
case "stripes":
|
case "stripes":
|
||||||
return stripesComp
|
return stripesComp;
|
||||||
case "iris bloom":
|
case "iris bloom":
|
||||||
return irisComp
|
return irisComp;
|
||||||
case "pixelate":
|
case "pixelate":
|
||||||
return pixelateComp
|
return pixelateComp;
|
||||||
case "portal":
|
case "portal":
|
||||||
return portalComp
|
return portalComp;
|
||||||
default:
|
default:
|
||||||
return null
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -448,15 +453,17 @@ Variants {
|
|||||||
duration: root.actualTransitionType === "none" ? 0 : 1000
|
duration: root.actualTransitionType === "none" ? 0 : 1000
|
||||||
easing.type: Easing.InOutCubic
|
easing.type: Easing.InOutCubic
|
||||||
onFinished: {
|
onFinished: {
|
||||||
|
const tempSource = nextWallpaper.source;
|
||||||
|
if (tempSource && nextWallpaper.status === Image.Ready && !tempSource.toString().startsWith("#")) {
|
||||||
|
currentWallpaper.source = tempSource;
|
||||||
|
}
|
||||||
|
root.transitionProgress = 0.0;
|
||||||
|
currentWallpaper.visible = root.actualTransitionType === "none";
|
||||||
|
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
if (nextWallpaper.source && nextWallpaper.status === Image.Ready && !nextWallpaper.source.toString().startsWith("#")) {
|
nextWallpaper.source = "";
|
||||||
currentWallpaper.source = nextWallpaper.source
|
nextWallpaper.visible = false;
|
||||||
}
|
});
|
||||||
nextWallpaper.source = ""
|
|
||||||
nextWallpaper.visible = false
|
|
||||||
currentWallpaper.visible = root.actualTransitionType === "none"
|
|
||||||
root.transitionProgress = 0.0
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
pragma Singleton
|
pragma Singleton
|
||||||
|
|
||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Services.Notifications
|
import Quickshell.Services.Notifications
|
||||||
import Quickshell.Widgets
|
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import "../Common/markdown2html.js" as Markdown2Html
|
import "../Common/markdown2html.js" as Markdown2Html
|
||||||
|
|
||||||
@@ -28,108 +26,106 @@ Singleton {
|
|||||||
property int maxIngressPerSecond: 20
|
property int maxIngressPerSecond: 20
|
||||||
property double _lastIngressSec: 0
|
property double _lastIngressSec: 0
|
||||||
property int _ingressCountThisSec: 0
|
property int _ingressCountThisSec: 0
|
||||||
property int maxStoredNotifications: 300
|
property int maxStoredNotifications: 50
|
||||||
|
|
||||||
property var _dismissQueue: []
|
property var _dismissQueue: []
|
||||||
property int _dismissBatchSize: 8
|
property int _dismissBatchSize: 8
|
||||||
property int _dismissTickMs: 8
|
property int _dismissTickMs: 8
|
||||||
property bool _suspendGrouping: false
|
property bool _suspendGrouping: false
|
||||||
property var _groupCache: ({
|
property var _groupCache: ({
|
||||||
"notifications": [],
|
"notifications": [],
|
||||||
"popups": []
|
"popups": []
|
||||||
})
|
})
|
||||||
property bool _groupsDirty: false
|
property bool _groupsDirty: false
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
_recomputeGroups()
|
_recomputeGroups();
|
||||||
}
|
}
|
||||||
|
|
||||||
function _nowSec() {
|
function _nowSec() {
|
||||||
return Date.now() / 1000.0
|
return Date.now() / 1000.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _ingressAllowed(notif) {
|
function _ingressAllowed(notif) {
|
||||||
const t = _nowSec()
|
const t = _nowSec();
|
||||||
if (t - _lastIngressSec >= 1.0) {
|
if (t - _lastIngressSec >= 1.0) {
|
||||||
_lastIngressSec = t
|
_lastIngressSec = t;
|
||||||
_ingressCountThisSec = 0
|
_ingressCountThisSec = 0;
|
||||||
}
|
}
|
||||||
_ingressCountThisSec += 1
|
_ingressCountThisSec += 1;
|
||||||
if (notif.urgency === NotificationUrgency.Critical) {
|
if (notif.urgency === NotificationUrgency.Critical) {
|
||||||
return true
|
return true;
|
||||||
}
|
}
|
||||||
return _ingressCountThisSec <= maxIngressPerSecond
|
return _ingressCountThisSec <= maxIngressPerSecond;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _enqueuePopup(wrapper) {
|
function _enqueuePopup(wrapper) {
|
||||||
if (notificationQueue.length >= maxQueueSize) {
|
if (notificationQueue.length >= maxQueueSize) {
|
||||||
const gk = getGroupKey(wrapper)
|
const gk = getGroupKey(wrapper);
|
||||||
let idx = notificationQueue.findIndex(w => w && getGroupKey(w) === gk && w.urgency !== NotificationUrgency.Critical)
|
let idx = notificationQueue.findIndex(w => w && getGroupKey(w) === gk && w.urgency !== NotificationUrgency.Critical);
|
||||||
if (idx === -1) {
|
if (idx === -1) {
|
||||||
idx = notificationQueue.findIndex(w => w && w.urgency !== NotificationUrgency.Critical)
|
idx = notificationQueue.findIndex(w => w && w.urgency !== NotificationUrgency.Critical);
|
||||||
}
|
}
|
||||||
if (idx === -1) {
|
if (idx === -1) {
|
||||||
idx = 0
|
idx = 0;
|
||||||
}
|
}
|
||||||
const victim = notificationQueue[idx]
|
const victim = notificationQueue[idx];
|
||||||
if (victim) {
|
if (victim) {
|
||||||
victim.popup = false
|
victim.popup = false;
|
||||||
}
|
}
|
||||||
notificationQueue.splice(idx, 1)
|
notificationQueue.splice(idx, 1);
|
||||||
}
|
}
|
||||||
notificationQueue = [...notificationQueue, wrapper]
|
notificationQueue = [...notificationQueue, wrapper];
|
||||||
}
|
}
|
||||||
|
|
||||||
function _initWrapperPersistence(wrapper) {
|
function _initWrapperPersistence(wrapper) {
|
||||||
const timeoutMs = wrapper.timer ? wrapper.timer.interval : 5000
|
const timeoutMs = wrapper.timer ? wrapper.timer.interval : 5000;
|
||||||
const isCritical = wrapper.notification && wrapper.notification.urgency === NotificationUrgency.Critical
|
const isCritical = wrapper.notification && wrapper.notification.urgency === NotificationUrgency.Critical;
|
||||||
wrapper.isPersistent = isCritical || (timeoutMs === 0)
|
wrapper.isPersistent = isCritical || (timeoutMs === 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _trimStored() {
|
function _trimStored() {
|
||||||
if (notifications.length > maxStoredNotifications) {
|
if (notifications.length > maxStoredNotifications) {
|
||||||
const overflow = notifications.length - maxStoredNotifications
|
const overflow = notifications.length - maxStoredNotifications;
|
||||||
const toDrop = []
|
const toDrop = [];
|
||||||
for (var i = notifications.length - 1; i >= 0 && toDrop.length < overflow; --i) {
|
for (var i = notifications.length - 1; i >= 0 && toDrop.length < overflow; --i) {
|
||||||
const w = notifications[i]
|
const w = notifications[i];
|
||||||
if (w && w.notification && w.urgency !== NotificationUrgency.Critical) {
|
if (w && w.notification && w.urgency !== NotificationUrgency.Critical) {
|
||||||
toDrop.push(w)
|
toDrop.push(w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (var i = notifications.length - 1; i >= 0 && toDrop.length < overflow; --i) {
|
for (var i = notifications.length - 1; i >= 0 && toDrop.length < overflow; --i) {
|
||||||
const w = notifications[i]
|
const w = notifications[i];
|
||||||
if (w && w.notification && toDrop.indexOf(w) === -1) {
|
if (w && w.notification && toDrop.indexOf(w) === -1) {
|
||||||
toDrop.push(w)
|
toDrop.push(w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const w of toDrop) {
|
for (const w of toDrop) {
|
||||||
try {
|
try {
|
||||||
w.notification.dismiss()
|
w.notification.dismiss();
|
||||||
} catch (e) {
|
} catch (e) {}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onOverlayOpen() {
|
function onOverlayOpen() {
|
||||||
popupsDisabled = true
|
popupsDisabled = true;
|
||||||
addGate.stop()
|
addGate.stop();
|
||||||
addGateBusy = false
|
addGateBusy = false;
|
||||||
|
|
||||||
notificationQueue = []
|
notificationQueue = [];
|
||||||
for (const w of visibleNotifications) {
|
for (const w of visibleNotifications) {
|
||||||
if (w) {
|
if (w) {
|
||||||
w.popup = false
|
w.popup = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
visibleNotifications = []
|
visibleNotifications = [];
|
||||||
_recomputeGroupsLater()
|
_recomputeGroupsLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onOverlayClose() {
|
function onOverlayClose() {
|
||||||
popupsDisabled = false
|
popupsDisabled = false;
|
||||||
processQueue()
|
processQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
@@ -138,8 +134,8 @@ Singleton {
|
|||||||
running: false
|
running: false
|
||||||
repeat: false
|
repeat: false
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
addGateBusy = false
|
addGateBusy = false;
|
||||||
processQueue()
|
processQueue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,7 +146,7 @@ Singleton {
|
|||||||
running: root.allWrappers.length > 0 || visibleNotifications.length > 0
|
running: root.allWrappers.length > 0 || visibleNotifications.length > 0
|
||||||
triggeredOnStart: false
|
triggeredOnStart: false
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
root.timeUpdateTick = !root.timeUpdateTick
|
root.timeUpdateTick = !root.timeUpdateTick;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,23 +156,21 @@ Singleton {
|
|||||||
repeat: true
|
repeat: true
|
||||||
running: false
|
running: false
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
let n = Math.min(_dismissBatchSize, _dismissQueue.length)
|
let n = Math.min(_dismissBatchSize, _dismissQueue.length);
|
||||||
for (var i = 0; i < n; ++i) {
|
for (var i = 0; i < n; ++i) {
|
||||||
const w = _dismissQueue.pop()
|
const w = _dismissQueue.pop();
|
||||||
try {
|
try {
|
||||||
if (w && w.notification) {
|
if (w && w.notification) {
|
||||||
w.notification.dismiss()
|
w.notification.dismiss();
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (_dismissQueue.length === 0) {
|
if (_dismissQueue.length === 0) {
|
||||||
dismissPump.stop()
|
dismissPump.stop();
|
||||||
_suspendGrouping = false
|
_suspendGrouping = false;
|
||||||
bulkDismissing = false
|
bulkDismissing = false;
|
||||||
popupsDisabled = false
|
popupsDisabled = false;
|
||||||
_recomputeGroupsLater()
|
_recomputeGroupsLater();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -212,52 +206,50 @@ Singleton {
|
|||||||
persistenceSupported: true
|
persistenceSupported: true
|
||||||
|
|
||||||
onNotification: notif => {
|
onNotification: notif => {
|
||||||
notif.tracked = true
|
notif.tracked = true;
|
||||||
|
|
||||||
if (!_ingressAllowed(notif)) {
|
if (!_ingressAllowed(notif)) {
|
||||||
if (notif.urgency !== NotificationUrgency.Critical) {
|
if (notif.urgency !== NotificationUrgency.Critical) {
|
||||||
try {
|
try {
|
||||||
notif.dismiss()
|
notif.dismiss();
|
||||||
} catch (e) {
|
} catch (e) {}
|
||||||
|
return;
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SettingsData.soundsEnabled && SettingsData.soundNewNotification) {
|
if (SettingsData.soundsEnabled && SettingsData.soundNewNotification) {
|
||||||
if (notif.urgency === NotificationUrgency.Critical) {
|
if (notif.urgency === NotificationUrgency.Critical) {
|
||||||
AudioService.playCriticalNotificationSound()
|
AudioService.playCriticalNotificationSound();
|
||||||
} else {
|
} else {
|
||||||
AudioService.playNormalNotificationSound()
|
AudioService.playNormalNotificationSound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const shouldShowPopup = !root.popupsDisabled && !SessionData.doNotDisturb
|
const shouldShowPopup = !root.popupsDisabled && !SessionData.doNotDisturb;
|
||||||
const isTransient = notif.transient
|
const isTransient = notif.transient;
|
||||||
const wrapper = notifComponent.createObject(root, {
|
const wrapper = notifComponent.createObject(root, {
|
||||||
"popup": shouldShowPopup,
|
"popup": shouldShowPopup,
|
||||||
"notification": notif
|
"notification": notif
|
||||||
})
|
});
|
||||||
|
|
||||||
if (wrapper) {
|
if (wrapper) {
|
||||||
root.allWrappers.push(wrapper)
|
root.allWrappers.push(wrapper);
|
||||||
if (!isTransient) {
|
if (!isTransient) {
|
||||||
root.notifications.push(wrapper)
|
root.notifications.push(wrapper);
|
||||||
_trimStored()
|
_trimStored();
|
||||||
}
|
}
|
||||||
|
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
_initWrapperPersistence(wrapper)
|
_initWrapperPersistence(wrapper);
|
||||||
})
|
});
|
||||||
|
|
||||||
if (shouldShowPopup) {
|
if (shouldShowPopup) {
|
||||||
_enqueuePopup(wrapper)
|
_enqueuePopup(wrapper);
|
||||||
processQueue()
|
processQueue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_recomputeGroupsLater()
|
_recomputeGroupsLater();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,80 +263,80 @@ Singleton {
|
|||||||
|
|
||||||
onPopupChanged: {
|
onPopupChanged: {
|
||||||
if (!popup) {
|
if (!popup) {
|
||||||
removeFromVisibleNotifications(wrapper)
|
removeFromVisibleNotifications(wrapper);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property Timer timer: Timer {
|
readonly property Timer timer: Timer {
|
||||||
interval: {
|
interval: {
|
||||||
if (!wrapper.notification) {
|
if (!wrapper.notification) {
|
||||||
return 5000
|
return 5000;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (wrapper.notification.urgency) {
|
switch (wrapper.notification.urgency) {
|
||||||
case NotificationUrgency.Low:
|
case NotificationUrgency.Low:
|
||||||
return SettingsData.notificationTimeoutLow
|
return SettingsData.notificationTimeoutLow;
|
||||||
case NotificationUrgency.Critical:
|
case NotificationUrgency.Critical:
|
||||||
return SettingsData.notificationTimeoutCritical
|
return SettingsData.notificationTimeoutCritical;
|
||||||
default:
|
default:
|
||||||
return SettingsData.notificationTimeoutNormal
|
return SettingsData.notificationTimeoutNormal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
repeat: false
|
repeat: false
|
||||||
running: false
|
running: false
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
if (interval > 0) {
|
if (interval > 0) {
|
||||||
wrapper.popup = false
|
wrapper.popup = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property date time: new Date()
|
readonly property date time: new Date()
|
||||||
readonly property string timeStr: {
|
readonly property string timeStr: {
|
||||||
root.timeUpdateTick
|
root.timeUpdateTick;
|
||||||
root.clockFormatChanged
|
root.clockFormatChanged;
|
||||||
|
|
||||||
const now = new Date()
|
const now = new Date();
|
||||||
const diff = now.getTime() - time.getTime()
|
const diff = now.getTime() - time.getTime();
|
||||||
const minutes = Math.floor(diff / 60000)
|
const minutes = Math.floor(diff / 60000);
|
||||||
const hours = Math.floor(minutes / 60)
|
const hours = Math.floor(minutes / 60);
|
||||||
|
|
||||||
if (hours < 1) {
|
if (hours < 1) {
|
||||||
if (minutes < 1) {
|
if (minutes < 1) {
|
||||||
return "now"
|
return "now";
|
||||||
}
|
}
|
||||||
return `${minutes}m ago`
|
return `${minutes}m ago`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const nowDate = new Date(now.getFullYear(), now.getMonth(), now.getDate())
|
const nowDate = new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
||||||
const timeDate = new Date(time.getFullYear(), time.getMonth(), time.getDate())
|
const timeDate = new Date(time.getFullYear(), time.getMonth(), time.getDate());
|
||||||
const daysDiff = Math.floor((nowDate - timeDate) / (1000 * 60 * 60 * 24))
|
const daysDiff = Math.floor((nowDate - timeDate) / (1000 * 60 * 60 * 24));
|
||||||
|
|
||||||
if (daysDiff === 0) {
|
if (daysDiff === 0) {
|
||||||
return formatTime(time)
|
return formatTime(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (daysDiff === 1) {
|
if (daysDiff === 1) {
|
||||||
return `yesterday, ${formatTime(time)}`
|
return `yesterday, ${formatTime(time)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return `${daysDiff} days ago`
|
return `${daysDiff} days ago`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatTime(date) {
|
function formatTime(date) {
|
||||||
let use24Hour = true
|
let use24Hour = true;
|
||||||
try {
|
try {
|
||||||
if (typeof SettingsData !== "undefined" && SettingsData.use24HourClock !== undefined) {
|
if (typeof SettingsData !== "undefined" && SettingsData.use24HourClock !== undefined) {
|
||||||
use24Hour = SettingsData.use24HourClock
|
use24Hour = SettingsData.use24HourClock;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
use24Hour = true
|
use24Hour = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use24Hour) {
|
if (use24Hour) {
|
||||||
return date.toLocaleTimeString(Qt.locale(), "HH:mm")
|
return date.toLocaleTimeString(Qt.locale(), "HH:mm");
|
||||||
} else {
|
} else {
|
||||||
return date.toLocaleTimeString(Qt.locale(), "h:mm AP")
|
return date.toLocaleTimeString(Qt.locale(), "h:mm AP");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,27 +345,27 @@ Singleton {
|
|||||||
readonly property string body: notification.body
|
readonly property string body: notification.body
|
||||||
readonly property string htmlBody: {
|
readonly property string htmlBody: {
|
||||||
if (body && (body.includes('<') && body.includes('>'))) {
|
if (body && (body.includes('<') && body.includes('>'))) {
|
||||||
return body
|
return body;
|
||||||
}
|
}
|
||||||
return Markdown2Html.markdownToHtml(body)
|
return Markdown2Html.markdownToHtml(body);
|
||||||
}
|
}
|
||||||
readonly property string appIcon: notification.appIcon
|
readonly property string appIcon: notification.appIcon
|
||||||
readonly property string appName: {
|
readonly property string appName: {
|
||||||
if (notification.appName == "") {
|
if (notification.appName == "") {
|
||||||
const entry = DesktopEntries.heuristicLookup(notification.desktopEntry)
|
const entry = DesktopEntries.heuristicLookup(notification.desktopEntry);
|
||||||
if (entry && entry.name) {
|
if (entry && entry.name) {
|
||||||
return entry.name.toLowerCase()
|
return entry.name.toLowerCase();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return notification.appName || "app"
|
return notification.appName || "app";
|
||||||
}
|
}
|
||||||
readonly property string desktopEntry: notification.desktopEntry
|
readonly property string desktopEntry: notification.desktopEntry
|
||||||
readonly property string image: notification.image
|
readonly property string image: notification.image
|
||||||
readonly property string cleanImage: {
|
readonly property string cleanImage: {
|
||||||
if (!image) {
|
if (!image) {
|
||||||
return ""
|
return "";
|
||||||
}
|
}
|
||||||
return Paths.strip(image)
|
return Paths.strip(image);
|
||||||
}
|
}
|
||||||
readonly property int urgency: notification.urgency
|
readonly property int urgency: notification.urgency
|
||||||
readonly property list<NotificationAction> actions: notification.actions
|
readonly property list<NotificationAction> actions: notification.actions
|
||||||
@@ -382,26 +374,26 @@ Singleton {
|
|||||||
target: wrapper.notification.Retainable
|
target: wrapper.notification.Retainable
|
||||||
|
|
||||||
function onDropped(): void {
|
function onDropped(): void {
|
||||||
root.allWrappers = root.allWrappers.filter(w => w !== wrapper)
|
root.allWrappers = root.allWrappers.filter(w => w !== wrapper);
|
||||||
root.notifications = root.notifications.filter(w => w !== wrapper)
|
root.notifications = root.notifications.filter(w => w !== wrapper);
|
||||||
|
|
||||||
if (root.bulkDismissing) {
|
if (root.bulkDismissing) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const groupKey = getGroupKey(wrapper)
|
const groupKey = getGroupKey(wrapper);
|
||||||
const remainingInGroup = root.notifications.filter(n => getGroupKey(n) === groupKey)
|
const remainingInGroup = root.notifications.filter(n => getGroupKey(n) === groupKey);
|
||||||
|
|
||||||
if (remainingInGroup.length <= 1) {
|
if (remainingInGroup.length <= 1) {
|
||||||
clearGroupExpansionState(groupKey)
|
clearGroupExpansionState(groupKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanupExpansionStates()
|
cleanupExpansionStates();
|
||||||
root._recomputeGroupsLater()
|
root._recomputeGroupsLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onAboutToDestroy(): void {
|
function onAboutToDestroy(): void {
|
||||||
wrapper.destroy()
|
wrapper.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -414,146 +406,145 @@ Singleton {
|
|||||||
function clearAllPopups() {
|
function clearAllPopups() {
|
||||||
for (const w of visibleNotifications) {
|
for (const w of visibleNotifications) {
|
||||||
if (w) {
|
if (w) {
|
||||||
w.popup = false
|
w.popup = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
visibleNotifications = []
|
visibleNotifications = [];
|
||||||
notificationQueue = []
|
notificationQueue = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearAllNotifications() {
|
function clearAllNotifications() {
|
||||||
bulkDismissing = true
|
bulkDismissing = true;
|
||||||
popupsDisabled = true
|
popupsDisabled = true;
|
||||||
addGate.stop()
|
addGate.stop();
|
||||||
addGateBusy = false
|
addGateBusy = false;
|
||||||
notificationQueue = []
|
notificationQueue = [];
|
||||||
|
|
||||||
for (const w of allWrappers) {
|
for (const w of allWrappers) {
|
||||||
if (w) {
|
if (w) {
|
||||||
w.popup = false
|
w.popup = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
visibleNotifications = []
|
visibleNotifications = [];
|
||||||
|
|
||||||
_dismissQueue = notifications.slice()
|
_dismissQueue = notifications.slice();
|
||||||
if (notifications.length) {
|
if (notifications.length) {
|
||||||
notifications = []
|
notifications = [];
|
||||||
}
|
}
|
||||||
expandedGroups = {}
|
expandedGroups = {};
|
||||||
expandedMessages = {}
|
expandedMessages = {};
|
||||||
|
|
||||||
_suspendGrouping = true
|
_suspendGrouping = true;
|
||||||
|
|
||||||
if (!dismissPump.running && _dismissQueue.length) {
|
if (!dismissPump.running && _dismissQueue.length) {
|
||||||
dismissPump.start()
|
dismissPump.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function dismissNotification(wrapper) {
|
function dismissNotification(wrapper) {
|
||||||
if (!wrapper || !wrapper.notification) {
|
if (!wrapper || !wrapper.notification) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
wrapper.popup = false
|
wrapper.popup = false;
|
||||||
wrapper.notification.dismiss()
|
wrapper.notification.dismiss();
|
||||||
}
|
}
|
||||||
|
|
||||||
function disablePopups(disable) {
|
function disablePopups(disable) {
|
||||||
popupsDisabled = disable
|
popupsDisabled = disable;
|
||||||
if (disable) {
|
if (disable) {
|
||||||
notificationQueue = []
|
notificationQueue = [];
|
||||||
for (const notif of visibleNotifications) {
|
for (const notif of visibleNotifications) {
|
||||||
notif.popup = false
|
notif.popup = false;
|
||||||
}
|
}
|
||||||
visibleNotifications = []
|
visibleNotifications = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function processQueue() {
|
function processQueue() {
|
||||||
if (addGateBusy) {
|
if (addGateBusy) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
if (popupsDisabled) {
|
if (popupsDisabled) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
if (SessionData.doNotDisturb) {
|
if (SessionData.doNotDisturb) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
if (notificationQueue.length === 0) {
|
if (notificationQueue.length === 0) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const activePopupCount = visibleNotifications.filter(n => n && n.popup).length
|
const activePopupCount = visibleNotifications.filter(n => n && n.popup).length;
|
||||||
if (activePopupCount >= 4) {
|
if (activePopupCount >= 4) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const next = notificationQueue.shift()
|
const next = notificationQueue.shift();
|
||||||
|
|
||||||
next.seq = ++seqCounter
|
next.seq = ++seqCounter;
|
||||||
visibleNotifications = [...visibleNotifications, next]
|
visibleNotifications = [...visibleNotifications, next];
|
||||||
next.popup = true
|
next.popup = true;
|
||||||
|
|
||||||
if (next.timer.interval > 0) {
|
if (next.timer.interval > 0) {
|
||||||
next.timer.start()
|
next.timer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
addGateBusy = true
|
addGateBusy = true;
|
||||||
addGate.restart()
|
addGate.restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeFromVisibleNotifications(wrapper) {
|
function removeFromVisibleNotifications(wrapper) {
|
||||||
visibleNotifications = visibleNotifications.filter(n => n !== wrapper)
|
visibleNotifications = visibleNotifications.filter(n => n !== wrapper);
|
||||||
processQueue()
|
processQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
function releaseWrapper(w) {
|
function releaseWrapper(w) {
|
||||||
visibleNotifications = visibleNotifications.filter(n => n !== w)
|
visibleNotifications = visibleNotifications.filter(n => n !== w);
|
||||||
notificationQueue = notificationQueue.filter(n => n !== w)
|
notificationQueue = notificationQueue.filter(n => n !== w);
|
||||||
|
|
||||||
if (w && w.destroy && !w.isPersistent && notifications.indexOf(w) === -1) {
|
if (w && w.destroy && !w.isPersistent && notifications.indexOf(w) === -1) {
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
try {
|
try {
|
||||||
w.destroy()
|
w.destroy();
|
||||||
} catch (e) {
|
} catch (e) {}
|
||||||
|
});
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getGroupKey(wrapper) {
|
function getGroupKey(wrapper) {
|
||||||
if (wrapper.desktopEntry && wrapper.desktopEntry !== "") {
|
if (wrapper.desktopEntry && wrapper.desktopEntry !== "") {
|
||||||
return wrapper.desktopEntry.toLowerCase()
|
return wrapper.desktopEntry.toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
return wrapper.appName.toLowerCase()
|
return wrapper.appName.toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
function _recomputeGroups() {
|
function _recomputeGroups() {
|
||||||
if (_suspendGrouping) {
|
if (_suspendGrouping) {
|
||||||
_groupsDirty = true
|
_groupsDirty = true;
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
_groupCache = {
|
_groupCache = {
|
||||||
"notifications": _calcGroupedNotifications(),
|
"notifications": _calcGroupedNotifications(),
|
||||||
"popups": _calcGroupedPopups()
|
"popups": _calcGroupedPopups()
|
||||||
}
|
};
|
||||||
_groupsDirty = false
|
_groupsDirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _recomputeGroupsLater() {
|
function _recomputeGroupsLater() {
|
||||||
_groupsDirty = true
|
_groupsDirty = true;
|
||||||
if (!groupsDebounce.running) {
|
if (!groupsDebounce.running) {
|
||||||
groupsDebounce.start()
|
groupsDebounce.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function _calcGroupedNotifications() {
|
function _calcGroupedNotifications() {
|
||||||
const groups = {}
|
const groups = {};
|
||||||
|
|
||||||
for (const notif of notifications) {
|
for (const notif of notifications) {
|
||||||
if (!notif) continue
|
if (!notif)
|
||||||
const groupKey = getGroupKey(notif)
|
continue;
|
||||||
|
const groupKey = getGroupKey(notif);
|
||||||
if (!groups[groupKey]) {
|
if (!groups[groupKey]) {
|
||||||
groups[groupKey] = {
|
groups[groupKey] = {
|
||||||
"key": groupKey,
|
"key": groupKey,
|
||||||
@@ -562,34 +553,35 @@ Singleton {
|
|||||||
"latestNotification": null,
|
"latestNotification": null,
|
||||||
"count": 0,
|
"count": 0,
|
||||||
"hasInlineReply": false
|
"hasInlineReply": false
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
groups[groupKey].notifications.unshift(notif)
|
groups[groupKey].notifications.unshift(notif);
|
||||||
groups[groupKey].latestNotification = groups[groupKey].notifications[0]
|
groups[groupKey].latestNotification = groups[groupKey].notifications[0];
|
||||||
groups[groupKey].count = groups[groupKey].notifications.length
|
groups[groupKey].count = groups[groupKey].notifications.length;
|
||||||
|
|
||||||
if (notif.notification.hasInlineReply) {
|
if (notif.notification.hasInlineReply) {
|
||||||
groups[groupKey].hasInlineReply = true
|
groups[groupKey].hasInlineReply = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Object.values(groups).sort((a, b) => {
|
return Object.values(groups).sort((a, b) => {
|
||||||
const aUrgency = a.latestNotification.urgency || NotificationUrgency.Low
|
const aUrgency = a.latestNotification.urgency || NotificationUrgency.Low;
|
||||||
const bUrgency = b.latestNotification.urgency || NotificationUrgency.Low
|
const bUrgency = b.latestNotification.urgency || NotificationUrgency.Low;
|
||||||
if (aUrgency !== bUrgency) {
|
if (aUrgency !== bUrgency) {
|
||||||
return bUrgency - aUrgency
|
return bUrgency - aUrgency;
|
||||||
}
|
}
|
||||||
return b.latestNotification.time.getTime() - a.latestNotification.time.getTime()
|
return b.latestNotification.time.getTime() - a.latestNotification.time.getTime();
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function _calcGroupedPopups() {
|
function _calcGroupedPopups() {
|
||||||
const groups = {}
|
const groups = {};
|
||||||
|
|
||||||
for (const notif of popups) {
|
for (const notif of popups) {
|
||||||
if (!notif) continue
|
if (!notif)
|
||||||
const groupKey = getGroupKey(notif)
|
continue;
|
||||||
|
const groupKey = getGroupKey(notif);
|
||||||
if (!groups[groupKey]) {
|
if (!groups[groupKey]) {
|
||||||
groups[groupKey] = {
|
groups[groupKey] = {
|
||||||
"key": groupKey,
|
"key": groupKey,
|
||||||
@@ -598,92 +590,92 @@ Singleton {
|
|||||||
"latestNotification": null,
|
"latestNotification": null,
|
||||||
"count": 0,
|
"count": 0,
|
||||||
"hasInlineReply": false
|
"hasInlineReply": false
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
groups[groupKey].notifications.unshift(notif)
|
groups[groupKey].notifications.unshift(notif);
|
||||||
groups[groupKey].latestNotification = groups[groupKey].notifications[0]
|
groups[groupKey].latestNotification = groups[groupKey].notifications[0];
|
||||||
groups[groupKey].count = groups[groupKey].notifications.length
|
groups[groupKey].count = groups[groupKey].notifications.length;
|
||||||
|
|
||||||
if (notif.notification.hasInlineReply) {
|
if (notif.notification.hasInlineReply) {
|
||||||
groups[groupKey].hasInlineReply = true
|
groups[groupKey].hasInlineReply = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Object.values(groups).sort((a, b) => {
|
return Object.values(groups).sort((a, b) => {
|
||||||
return b.latestNotification.time.getTime() - a.latestNotification.time.getTime()
|
return b.latestNotification.time.getTime() - a.latestNotification.time.getTime();
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleGroupExpansion(groupKey) {
|
function toggleGroupExpansion(groupKey) {
|
||||||
let newExpandedGroups = {}
|
let newExpandedGroups = {};
|
||||||
for (const key in expandedGroups) {
|
for (const key in expandedGroups) {
|
||||||
newExpandedGroups[key] = expandedGroups[key]
|
newExpandedGroups[key] = expandedGroups[key];
|
||||||
}
|
}
|
||||||
newExpandedGroups[groupKey] = !newExpandedGroups[groupKey]
|
newExpandedGroups[groupKey] = !newExpandedGroups[groupKey];
|
||||||
expandedGroups = newExpandedGroups
|
expandedGroups = newExpandedGroups;
|
||||||
}
|
}
|
||||||
|
|
||||||
function dismissGroup(groupKey) {
|
function dismissGroup(groupKey) {
|
||||||
const group = groupedNotifications.find(g => g.key === groupKey)
|
const group = groupedNotifications.find(g => g.key === groupKey);
|
||||||
if (group) {
|
if (group) {
|
||||||
for (const notif of group.notifications) {
|
for (const notif of group.notifications) {
|
||||||
if (notif && notif.notification) {
|
if (notif && notif.notification) {
|
||||||
notif.notification.dismiss()
|
notif.notification.dismiss();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (const notif of allWrappers) {
|
for (const notif of allWrappers) {
|
||||||
if (notif && notif.notification && getGroupKey(notif) === groupKey) {
|
if (notif && notif.notification && getGroupKey(notif) === groupKey) {
|
||||||
notif.notification.dismiss()
|
notif.notification.dismiss();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearGroupExpansionState(groupKey) {
|
function clearGroupExpansionState(groupKey) {
|
||||||
let newExpandedGroups = {}
|
let newExpandedGroups = {};
|
||||||
for (const key in expandedGroups) {
|
for (const key in expandedGroups) {
|
||||||
if (key !== groupKey && expandedGroups[key]) {
|
if (key !== groupKey && expandedGroups[key]) {
|
||||||
newExpandedGroups[key] = true
|
newExpandedGroups[key] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expandedGroups = newExpandedGroups
|
expandedGroups = newExpandedGroups;
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanupExpansionStates() {
|
function cleanupExpansionStates() {
|
||||||
const currentGroupKeys = new Set(groupedNotifications.map(g => g.key))
|
const currentGroupKeys = new Set(groupedNotifications.map(g => g.key));
|
||||||
const currentMessageIds = new Set()
|
const currentMessageIds = new Set();
|
||||||
for (const group of groupedNotifications) {
|
for (const group of groupedNotifications) {
|
||||||
for (const notif of group.notifications) {
|
for (const notif of group.notifications) {
|
||||||
if (notif && notif.notification) {
|
if (notif && notif.notification) {
|
||||||
currentMessageIds.add(notif.notification.id)
|
currentMessageIds.add(notif.notification.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let newExpandedGroups = {}
|
let newExpandedGroups = {};
|
||||||
for (const key in expandedGroups) {
|
for (const key in expandedGroups) {
|
||||||
if (currentGroupKeys.has(key) && expandedGroups[key]) {
|
if (currentGroupKeys.has(key) && expandedGroups[key]) {
|
||||||
newExpandedGroups[key] = true
|
newExpandedGroups[key] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expandedGroups = newExpandedGroups
|
expandedGroups = newExpandedGroups;
|
||||||
let newExpandedMessages = {}
|
let newExpandedMessages = {};
|
||||||
for (const messageId in expandedMessages) {
|
for (const messageId in expandedMessages) {
|
||||||
if (currentMessageIds.has(messageId) && expandedMessages[messageId]) {
|
if (currentMessageIds.has(messageId) && expandedMessages[messageId]) {
|
||||||
newExpandedMessages[messageId] = true
|
newExpandedMessages[messageId] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expandedMessages = newExpandedMessages
|
expandedMessages = newExpandedMessages;
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleMessageExpansion(messageId) {
|
function toggleMessageExpansion(messageId) {
|
||||||
let newExpandedMessages = {}
|
let newExpandedMessages = {};
|
||||||
for (const key in expandedMessages) {
|
for (const key in expandedMessages) {
|
||||||
newExpandedMessages[key] = expandedMessages[key]
|
newExpandedMessages[key] = expandedMessages[key];
|
||||||
}
|
}
|
||||||
newExpandedMessages[messageId] = !newExpandedMessages[messageId]
|
newExpandedMessages[messageId] = !newExpandedMessages[messageId];
|
||||||
expandedMessages = newExpandedMessages
|
expandedMessages = newExpandedMessages;
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
@@ -692,13 +684,13 @@ Singleton {
|
|||||||
if (SessionData.doNotDisturb) {
|
if (SessionData.doNotDisturb) {
|
||||||
// Hide all current popups when DND is enabled
|
// Hide all current popups when DND is enabled
|
||||||
for (const notif of visibleNotifications) {
|
for (const notif of visibleNotifications) {
|
||||||
notif.popup = false
|
notif.popup = false;
|
||||||
}
|
}
|
||||||
visibleNotifications = []
|
visibleNotifications = [];
|
||||||
notificationQueue = []
|
notificationQueue = [];
|
||||||
} else {
|
} else {
|
||||||
// Re-enable popup processing when DND is disabled
|
// Re-enable popup processing when DND is disabled
|
||||||
processQueue()
|
processQueue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -706,7 +698,7 @@ Singleton {
|
|||||||
Connections {
|
Connections {
|
||||||
target: typeof SettingsData !== "undefined" ? SettingsData : null
|
target: typeof SettingsData !== "undefined" ? SettingsData : null
|
||||||
function onUse24HourClockChanged() {
|
function onUse24HourClockChanged() {
|
||||||
root.clockFormatChanged = !root.clockFormatChanged
|
root.clockFormatChanged = !root.clockFormatChanged;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ Singleton {
|
|||||||
property var systemUpdatePopout: null
|
property var systemUpdatePopout: null
|
||||||
|
|
||||||
property var settingsModal: null
|
property var settingsModal: null
|
||||||
|
property var settingsModalLoader: null
|
||||||
property var clipboardHistoryModal: null
|
property var clipboardHistoryModal: null
|
||||||
property var spotlightModal: null
|
property var spotlightModal: null
|
||||||
property var powerMenuModal: null
|
property var powerMenuModal: null
|
||||||
@@ -191,14 +192,50 @@ Singleton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
property bool _settingsWantsOpen: false
|
||||||
|
property bool _settingsWantsToggle: false
|
||||||
|
|
||||||
function openSettings() {
|
function openSettings() {
|
||||||
settingsModal?.show();
|
if (settingsModal) {
|
||||||
|
settingsModal.show();
|
||||||
|
} else if (settingsModalLoader) {
|
||||||
|
_settingsWantsOpen = true;
|
||||||
|
_settingsWantsToggle = false;
|
||||||
|
settingsModalLoader.activeAsync = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeSettings() {
|
function closeSettings() {
|
||||||
settingsModal?.close();
|
settingsModal?.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toggleSettings() {
|
||||||
|
if (settingsModal) {
|
||||||
|
settingsModal.toggle();
|
||||||
|
} else if (settingsModalLoader) {
|
||||||
|
_settingsWantsToggle = true;
|
||||||
|
_settingsWantsOpen = false;
|
||||||
|
settingsModalLoader.activeAsync = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function unloadSettings() {
|
||||||
|
if (settingsModalLoader) {
|
||||||
|
settingsModal = null;
|
||||||
|
settingsModalLoader.active = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _onSettingsModalLoaded() {
|
||||||
|
if (_settingsWantsOpen) {
|
||||||
|
_settingsWantsOpen = false;
|
||||||
|
settingsModal?.show();
|
||||||
|
} else if (_settingsWantsToggle) {
|
||||||
|
_settingsWantsToggle = false;
|
||||||
|
settingsModal?.toggle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function openClipboardHistory() {
|
function openClipboardHistory() {
|
||||||
clipboardHistoryModal?.show();
|
clipboardHistoryModal?.show();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user