1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-04-05 05:12:05 -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

@@ -22,7 +22,7 @@ Singleton {
property list<NotifWrapper> notificationQueue: []
property list<NotifWrapper> visibleNotifications: []
property int maxVisibleNotifications: 3
property int maxVisibleNotifications: 4
property bool addGateBusy: false
property int enterAnimMs: 400
property int seqCounter: 0
@@ -158,10 +158,7 @@ Singleton {
continue;
const urg = typeof item.urgency === "number" ? item.urgency : 1;
const body = item.body || "";
let htmlBody = item.htmlBody || "";
if (!htmlBody && body) {
htmlBody = (body.includes('<') && body.includes('>')) ? body : Markdown2Html.markdownToHtml(body);
}
const htmlBody = item.htmlBody || _resolveHtmlBody(body);
loaded.push({
id: item.id || "",
summary: item.summary || "",
@@ -251,9 +248,15 @@ Singleton {
const timeStr = SettingsData.use24HourClock ? date.toLocaleTimeString(Qt.locale(), "HH:mm") : date.toLocaleTimeString(Qt.locale(), "h:mm AP");
if (daysDiff === 0)
return timeStr;
if (daysDiff === 1)
return I18n.tr("yesterday") + ", " + timeStr;
return I18n.tr("%1 days ago").arg(daysDiff);
try {
const localeName = (typeof Qt !== "undefined" && Qt.locale) ? Qt.locale().name : "en-US";
const weekday = date.toLocaleDateString(localeName, {
weekday: "long"
});
return weekday + ", " + timeStr;
} catch (e) {
return timeStr;
}
}
function _nowSec() {
@@ -484,7 +487,7 @@ Singleton {
Timer {
id: addGate
interval: enterAnimMs + 50
interval: 80
running: false
repeat: false
onTriggered: {
@@ -688,11 +691,15 @@ Singleton {
return formatTime(time);
}
if (daysDiff === 1) {
return `yesterday, ${formatTime(time)}`;
try {
const localeName = (typeof Qt !== "undefined" && Qt.locale) ? Qt.locale().name : "en-US";
const weekday = time.toLocaleDateString(localeName, {
weekday: "long"
});
return `${weekday}, ${formatTime(time)}`;
} catch (e) {
return formatTime(time);
}
return `${daysDiff} days ago`;
}
function formatTime(date) {
@@ -715,13 +722,7 @@ Singleton {
required property Notification notification
readonly property string summary: notification?.summary ?? ""
readonly property string body: notification?.body ?? ""
readonly property string htmlBody: {
if (!body)
return "";
if (body.includes('<') && body.includes('>'))
return body;
return Markdown2Html.markdownToHtml(body);
}
readonly property string htmlBody: root._resolveHtmlBody(body)
readonly property string appIcon: notification?.appIcon ?? ""
readonly property string appName: {
if (!notification)
@@ -837,39 +838,54 @@ Singleton {
}
}
function processQueue() {
if (addGateBusy) {
return;
}
if (popupsDisabled) {
return;
}
if (SessionData.doNotDisturb) {
return;
}
if (notificationQueue.length === 0) {
return;
}
property bool _processingQueue: false
const activePopupCount = visibleNotifications.filter(n => n && n.popup).length;
if (activePopupCount >= 4) {
function processQueue() {
if (addGateBusy || _processingQueue)
return;
}
if (popupsDisabled)
return;
if (SessionData.doNotDisturb)
return;
if (notificationQueue.length === 0)
return;
_processingQueue = true;
const next = notificationQueue.shift();
if (!next)
if (!next) {
_processingQueue = false;
return;
}
next.seq = ++seqCounter;
visibleNotifications = [...visibleNotifications, next];
const activePopups = visibleNotifications.filter(n => n && n.popup);
let evicted = null;
if (activePopups.length >= maxVisibleNotifications) {
const unhovered = activePopups.filter(n => n.timer?.running);
const pool = unhovered.length > 0 ? unhovered : activePopups;
evicted = pool.reduce((min, n) => (n.seq < min.seq) ? n : min, pool[0]);
if (evicted)
evicted.removedByLimit = true;
}
if (evicted) {
visibleNotifications = [...visibleNotifications.filter(n => n !== evicted), next];
} else {
visibleNotifications = [...visibleNotifications, next];
}
if (evicted)
evicted.popup = false;
next.popup = true;
if (next.timer.interval > 0) {
if (next.timer.interval > 0)
next.timer.start();
}
addGateBusy = true;
addGate.restart();
_processingQueue = false;
}
function removeFromVisibleNotifications(wrapper) {
@@ -890,6 +906,96 @@ Singleton {
}
}
function _decodeEntities(s) {
s = s.replace(/&#(\d+);/g, (_, n) => String.fromCodePoint(parseInt(n, 10)));
s = s.replace(/&#x([0-9a-fA-F]+);/g, (_, n) => String.fromCodePoint(parseInt(n, 16)));
return s.replace(/&([a-zA-Z][a-zA-Z0-9]*);/g, (match, name) => {
switch (name) {
case "amp":
return "&";
case "lt":
return "<";
case "gt":
return ">";
case "quot":
return "\"";
case "apos":
return "'";
case "nbsp":
return "\u00A0";
case "ndash":
return "\u2013";
case "mdash":
return "\u2014";
case "lsquo":
return "\u2018";
case "rsquo":
return "\u2019";
case "ldquo":
return "\u201C";
case "rdquo":
return "\u201D";
case "bull":
return "\u2022";
case "hellip":
return "\u2026";
case "trade":
return "\u2122";
case "copy":
return "\u00A9";
case "reg":
return "\u00AE";
case "deg":
return "\u00B0";
case "plusmn":
return "\u00B1";
case "times":
return "\u00D7";
case "divide":
return "\u00F7";
case "micro":
return "\u00B5";
case "middot":
return "\u00B7";
case "laquo":
return "\u00AB";
case "raquo":
return "\u00BB";
case "larr":
return "\u2190";
case "rarr":
return "\u2192";
case "uarr":
return "\u2191";
case "darr":
return "\u2193";
default:
return match;
}
});
}
function _resolveHtmlBody(body) {
if (!body)
return "";
if (/<\/?[a-z][\s\S]*>/i.test(body))
return body;
// Decode percent-encoded URLs (e.g. https%3A%2F%2F → https://)
body = body.replace(/\bhttps?%3A%2F%2F[^\s]+/gi, match => {
try { return decodeURIComponent(match); }
catch (e) { return match; }
});
if (/&(#\d+|#x[0-9a-fA-F]+|[a-zA-Z][a-zA-Z0-9]+);/.test(body)) {
const decoded = _decodeEntities(body);
if (/<\/?[a-z][\s\S]*>/i.test(decoded))
return decoded;
return Markdown2Html.markdownToHtml(decoded);
}
return Markdown2Html.markdownToHtml(body);
}
function getGroupKey(wrapper) {
if (wrapper.desktopEntry && wrapper.desktopEntry !== "") {
return wrapper.desktopEntry.toLowerCase();