1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-04-12 00:32:17 -04:00

Squashed commit of the following:

commit 051b7576f7
Author: purian23 <purian23@gmail.com>
Date:   Sun Feb 15 16:38:45 2026 -0500

    Height for realz

commit 7784488a61
Author: purian23 <purian23@gmail.com>
Date:   Sun Feb 15 16:34:09 2026 -0500

    Fix height and truncate text/URLs

commit 31b328d428
Author: bbedward <bbedward@gmail.com>
Date:   Sun Feb 15 16:25:57 2026 -0500

    notifications: handle URL encoding in markdown2html

commit dbb04f74a2
Author: bbedward <bbedward@gmail.com>
Date:   Sun Feb 15 16:10:20 2026 -0500

    notifications: more comprehensive decoder

commit b29c7192c2
Author: bbedward <bbedward@gmail.com>
Date:   Sun Feb 15 15:51:37 2026 -0500

    notifications: html unescape

commit 8a48fa11ec
Author: purian23 <purian23@gmail.com>
Date:   Sun Feb 15 15:04:33 2026 -0500

    Add expressive curve on init toast

commit ee124f5e04
Author: purian23 <purian23@gmail.com>
Date:   Sun Feb 15 15:02:16 2026 -0500

    Expressive curves on swipe & btn height

commit 0fce904635
Author: purian23 <purian23@gmail.com>
Date:   Sun Feb 15 13:40:02 2026 -0500

    Provide bottom button clearance

commit 00d3829999
Author: bbedward <bbedward@gmail.com>
Date:   Sun Feb 15 13:24:31 2026 -0500

    notifications: cleanup popup display logic

commit fd05768059
Author: purian23 <purian23@gmail.com>
Date:   Sun Feb 15 01:00:55 2026 -0500

    Add Privacy Mode
    - Smoother notification expansions
    - Shadow & Privacy Toggles

commit 0dba11d845
Author: purian23 <purian23@gmail.com>
Date:   Sat Feb 14 22:48:46 2026 -0500

    Further M3 enhancements

commit 949c216964
Author: purian23 <purian23@gmail.com>
Date:   Sat Feb 14 19:59:38 2026 -0500

    Right-Click to set Rules on Notifications directly

commit 62bc25782c
Author: bbedward <bbedward@gmail.com>
Date:   Fri Feb 13 21:44:27 2026 -0500

    notifications: fix compact spacing, reveal header bar, add bottom center
    position, pointing hand cursor fix

commit ed495d4396
Author: purian23 <purian23@gmail.com>
Date:   Fri Feb 13 20:25:40 2026 -0500

    Tighten init toast

commit ebe38322a0
Author: purian23 <purian23@gmail.com>
Date:   Fri Feb 13 20:09:59 2026 -0500

    Update more m3 baselines & spacing

commit b1735bb701
Author: purian23 <purian23@gmail.com>
Date:   Fri Feb 13 14:10:05 2026 -0500

    Expand rules on-Click

commit 9f13546b4d
Author: purian23 <purian23@gmail.com>
Date:   Fri Feb 13 12:59:29 2026 -0500

    Add Notification Rules
    - Additional right-click ops
    - Allow for 3rd boy line on init notification popup

commit be133b73c7
Author: purian23 <purian23@gmail.com>
Date:   Fri Feb 13 10:10:03 2026 -0500

    Truncate long title in groups

commit 4fc275bead
Author: bbedward <bbedward@gmail.com>
Date:   Thu Feb 12 23:27:34 2026 -0500

    notification: expand/collapse animation adjustment

commit 00e6172a68
Author: purian23 <purian23@gmail.com>
Date:   Thu Feb 12 22:50:11 2026 -0500

    Fix global warnings

commit 0772f6deb7
Author: purian23 <purian23@gmail.com>
Date:   Thu Feb 12 22:46:40 2026 -0500

    Tweak expansion duration

commit 0ffeed3ff0
Author: purian23 <purian23@gmail.com>
Date:   Thu Feb 12 22:16:16 2026 -0500

    notifications: Update Material 3 baselines
    - New right-click to mute option
    - New independent Notification Animation settings
This commit is contained in:
bbedward
2026-02-16 17:57:13 -05:00
parent 8399d64c2d
commit 196c421b75
18 changed files with 1693 additions and 565 deletions

View File

@@ -8,26 +8,23 @@ QtObject {
property var modelData
property int topMargin: 0
readonly property bool compactMode: SettingsData.notificationCompactMode
readonly property real cardPadding: compactMode ? Theme.spacingS : Theme.spacingM
readonly property real popupIconSize: compactMode ? 48 : 63
readonly property real cardPadding: compactMode ? Theme.notificationCardPaddingCompact : Theme.notificationCardPadding
readonly property real popupIconSize: compactMode ? Theme.notificationIconSizeCompact : Theme.notificationIconSizeNormal
readonly property real actionButtonHeight: compactMode ? 20 : 24
readonly property real popupSpacing: 4
readonly property int baseNotificationHeight: cardPadding * 2 + popupIconSize + actionButtonHeight + Theme.spacingS + popupSpacing
property int maxTargetNotifications: 4
property var popupWindows: [] // strong refs to windows (live until exitFinished)
readonly property real contentSpacing: compactMode ? Theme.spacingXS : Theme.spacingS
readonly property real popupSpacing: compactMode ? 0 : Theme.spacingXS
readonly property real collapsedContentHeight: Math.max(popupIconSize, Theme.fontSizeSmall * 1.2 + Theme.fontSizeMedium * 1.2 + Theme.fontSizeSmall * 1.2 * (compactMode ? 1 : 2))
readonly property int baseNotificationHeight: cardPadding * 2 + collapsedContentHeight + actionButtonHeight + contentSpacing + popupSpacing
property var popupWindows: []
property var destroyingWindows: new Set()
property var pendingDestroys: []
property int destroyDelayMs: 100
property var pendingCreates: []
property int createDelayMs: 50
property bool createBusy: false
property Component popupComponent
popupComponent: Component {
NotificationPopup {
onEntered: manager._onPopupEntered(this)
onExitStarted: manager._onPopupExitStarted(this)
onExitFinished: manager._onPopupExitFinished(this)
onPopupHeightChanged: manager._onPopupHeightChanged(this)
}
}
@@ -71,36 +68,6 @@ QtObject {
destroyTimer.restart();
}
property Timer createTimer: Timer {
interval: createDelayMs
running: false
repeat: false
onTriggered: manager._processCreateQueue()
}
function _processCreateQueue() {
createBusy = false;
if (pendingCreates.length === 0)
return;
const wrapper = pendingCreates.shift();
if (wrapper)
_doInsertNewestAtTop(wrapper);
if (pendingCreates.length > 0) {
createBusy = true;
createTimer.restart();
}
}
function _scheduleCreate(wrapper) {
if (!wrapper)
return;
pendingCreates.push(wrapper);
if (!createBusy) {
createBusy = true;
createTimer.restart();
}
}
sweeper: Timer {
interval: 500
running: false
@@ -126,14 +93,10 @@ QtObject {
}
if (toRemove.length) {
popupWindows = popupWindows.filter(p => toRemove.indexOf(p) === -1);
const survivors = _active().sort((a, b) => a.screenY - b.screenY);
for (let k = 0; k < survivors.length; ++k) {
survivors[k].screenY = topMargin + k * baseNotificationHeight;
}
_repositionAll();
}
if (popupWindows.length === 0) {
if (popupWindows.length === 0)
sweeper.stop();
}
}
}
@@ -145,105 +108,29 @@ QtObject {
return p && p.status !== Component.Null && !p._isDestroying && p.hasValidData;
}
function _canMakeRoomFor(wrapper) {
const activeWindows = _active();
if (activeWindows.length < maxTargetNotifications) {
return true;
}
if (!wrapper || !wrapper.notification) {
return false;
}
const incomingUrgency = wrapper.urgency || 0;
for (const p of activeWindows) {
if (!p.notificationData || !p.notificationData.notification) {
continue;
}
const existingUrgency = p.notificationData.urgency || 0;
if (existingUrgency < incomingUrgency) {
return true;
}
if (existingUrgency === incomingUrgency) {
const timer = p.notificationData.timer;
if (timer && !timer.running) {
return true;
}
}
}
return false;
}
function _makeRoomForNew(wrapper) {
const activeWindows = _active();
if (activeWindows.length < maxTargetNotifications) {
return;
}
const toRemove = _selectPopupToRemove(activeWindows, wrapper);
if (toRemove && !toRemove.exiting) {
toRemove.notificationData.removedByLimit = true;
toRemove.notificationData.popup = false;
if (toRemove.notificationData.timer) {
toRemove.notificationData.timer.stop();
}
}
}
function _selectPopupToRemove(activeWindows, incomingWrapper) {
const sortedWindows = activeWindows.slice().sort((a, b) => {
const aUrgency = (a.notificationData) ? a.notificationData.urgency || 0 : 0;
const bUrgency = (b.notificationData) ? b.notificationData.urgency || 0 : 0;
if (aUrgency !== bUrgency) {
return aUrgency - bUrgency;
}
const aTimer = a.notificationData && a.notificationData.timer;
const bTimer = b.notificationData && b.notificationData.timer;
const aRunning = aTimer && aTimer.running;
const bRunning = bTimer && bTimer.running;
if (aRunning !== bRunning) {
return aRunning ? 1 : -1;
}
return b.screenY - a.screenY;
});
return sortedWindows[0];
}
function _sync(newWrappers) {
for (const w of newWrappers) {
if (w && !_hasWindowFor(w)) {
insertNewestAtTop(w);
}
}
for (const p of popupWindows.slice()) {
if (!_isValidWindow(p)) {
if (!_isValidWindow(p) || p.exiting)
continue;
}
if (p.notificationData && newWrappers.indexOf(p.notificationData) === -1 && !p.exiting) {
if (p.notificationData && newWrappers.indexOf(p.notificationData) === -1) {
p.notificationData.removedByLimit = true;
p.notificationData.popup = false;
}
}
for (const w of newWrappers) {
if (w && !_hasWindowFor(w))
_insertAtTop(w);
}
}
function insertNewestAtTop(wrapper) {
if (!wrapper)
return;
if (createBusy || pendingCreates.length > 0) {
_scheduleCreate(wrapper);
return;
}
_doInsertNewestAtTop(wrapper);
function _popupHeight(p) {
return (p.alignedHeight || p.implicitHeight || (baseNotificationHeight - popupSpacing)) + popupSpacing;
}
function _doInsertNewestAtTop(wrapper) {
function _insertAtTop(wrapper) {
if (!wrapper)
return;
for (const p of popupWindows) {
if (!_isValidWindow(p))
continue;
if (p.exiting)
continue;
p.screenY = p.screenY + baseNotificationHeight;
}
const notificationId = wrapper && wrapper.notification ? wrapper.notification.id : "";
const notificationId = wrapper?.notification ? wrapper.notification.id : "";
const win = popupComponent.createObject(null, {
"notificationData": wrapper,
"notificationId": notificationId,
@@ -256,72 +143,70 @@ QtObject {
win.destroy();
return;
}
popupWindows.push(win);
createBusy = true;
createTimer.restart();
popupWindows.unshift(win);
_repositionAll();
if (!sweeper.running)
sweeper.start();
}
function _active() {
return popupWindows.filter(p => _isValidWindow(p) && p.notificationData && p.notificationData.popup && !p.exiting);
}
function _repositionAll() {
const active = popupWindows.filter(p => _isValidWindow(p) && p.notificationData?.popup && !p.exiting);
function _bottom() {
let b = null;
let maxY = -1;
for (const p of _active()) {
if (p.screenY > maxY) {
maxY = p.screenY;
b = p;
}
const pinnedSlots = [];
for (const p of active) {
if (!p.hovered)
continue;
pinnedSlots.push({
y: p.screenY,
end: p.screenY + _popupHeight(p)
});
}
pinnedSlots.sort((a, b) => a.y - b.y);
let currentY = topMargin;
for (const win of active) {
if (win.hovered)
continue;
for (const slot of pinnedSlots) {
if (currentY >= slot.y - 1 && currentY < slot.end)
currentY = slot.end;
}
win.screenY = currentY;
currentY += _popupHeight(win);
}
return b;
}
function _onPopupEntered(p) {
}
function _onPopupExitStarted(p) {
if (!p)
function _onPopupHeightChanged(p) {
if (!p || p.exiting || p._isDestroying)
return;
const survivors = _active().sort((a, b) => a.screenY - b.screenY);
for (let k = 0; k < survivors.length; ++k)
survivors[k].screenY = topMargin + k * baseNotificationHeight;
if (popupWindows.indexOf(p) === -1)
return;
_repositionAll();
}
function _onPopupExitFinished(p) {
if (!p) {
if (!p)
return;
}
const windowId = p.toString();
if (destroyingWindows.has(windowId)) {
if (destroyingWindows.has(windowId))
return;
}
destroyingWindows.add(windowId);
const i = popupWindows.indexOf(p);
if (i !== -1) {
popupWindows.splice(i, 1);
popupWindows = popupWindows.slice();
}
if (NotificationService.releaseWrapper && p.notificationData) {
if (NotificationService.releaseWrapper && p.notificationData)
NotificationService.releaseWrapper(p.notificationData);
}
_scheduleDestroy(p);
Qt.callLater(() => destroyingWindows.delete(windowId));
const survivors = _active().sort((a, b) => a.screenY - b.screenY);
for (let k = 0; k < survivors.length; ++k) {
survivors[k].screenY = topMargin + k * baseNotificationHeight;
}
_repositionAll();
}
function cleanupAllWindows() {
sweeper.stop();
destroyTimer.stop();
createTimer.stop();
pendingDestroys = [];
pendingCreates = [];
createBusy = false;
for (const p of popupWindows.slice()) {
if (p) {
try {