summaryrefslogtreecommitdiff
path: root/raveos-hyprland-theme/theme-data/dms/Modules/Notifications/Center/HistoryNotificationList.qml
diff options
context:
space:
mode:
authorNippy <nippy@rp1.hu>2026-05-08 19:50:49 +0200
committerNippy <nippy@rp1.hu>2026-05-08 19:50:49 +0200
commit3462bcc46ecf74f576ea4397f16492c16bd75b10 (patch)
treec5ab7aef4498647e057bda8d49c11e5f9dda74c9 /raveos-hyprland-theme/theme-data/dms/Modules/Notifications/Center/HistoryNotificationList.qml
parent56616f693b4f263cbf0d47da43b67424efa6022d (diff)
downloadRaveOS-PKGBUILD-3462bcc46ecf74f576ea4397f16492c16bd75b10.tar.gz
RaveOS-PKGBUILD-3462bcc46ecf74f576ea4397f16492c16bd75b10.zip
raveos update
Diffstat (limited to 'raveos-hyprland-theme/theme-data/dms/Modules/Notifications/Center/HistoryNotificationList.qml')
-rw-r--r--raveos-hyprland-theme/theme-data/dms/Modules/Notifications/Center/HistoryNotificationList.qml387
1 files changed, 387 insertions, 0 deletions
diff --git a/raveos-hyprland-theme/theme-data/dms/Modules/Notifications/Center/HistoryNotificationList.qml b/raveos-hyprland-theme/theme-data/dms/Modules/Notifications/Center/HistoryNotificationList.qml
new file mode 100644
index 0000000..69fea41
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/dms/Modules/Notifications/Center/HistoryNotificationList.qml
@@ -0,0 +1,387 @@
+import QtQuick
+import Quickshell
+import qs.Common
+import qs.Services
+import qs.Widgets
+
+Item {
+ id: root
+
+ property string selectedFilterKey: "all"
+ property var keyboardController: null
+ property bool keyboardActive: false
+ property int selectedIndex: -1
+ property bool showKeyboardHints: false
+
+ function getStartOfDay(date) {
+ const d = new Date(date);
+ d.setHours(0, 0, 0, 0);
+ return d;
+ }
+
+ function getFilterRange(key) {
+ const now = new Date();
+ const startOfToday = getStartOfDay(now);
+ const startOfYesterday = new Date(startOfToday.getTime() - 86400000);
+
+ switch (key) {
+ case "all":
+ return {
+ start: null,
+ end: null
+ };
+ case "1h":
+ return {
+ start: new Date(now.getTime() - 3600000),
+ end: null
+ };
+ case "today":
+ return {
+ start: startOfToday,
+ end: null
+ };
+ case "yesterday":
+ return {
+ start: startOfYesterday,
+ end: startOfToday
+ };
+ case "older":
+ return {
+ start: null,
+ end: getOlderCutoff()
+ };
+ case "7d":
+ return {
+ start: new Date(now.getTime() - 7 * 86400000),
+ end: null
+ };
+ case "30d":
+ return {
+ start: new Date(now.getTime() - 30 * 86400000),
+ end: null
+ };
+ default:
+ return {
+ start: null,
+ end: null
+ };
+ }
+ }
+
+ function countForFilter(key) {
+ const range = getFilterRange(key);
+ if (!range.start && !range.end)
+ return NotificationService.historyList.length;
+ return NotificationService.historyList.filter(n => {
+ const ts = n.timestamp;
+ if (range.start && ts < range.start.getTime())
+ return false;
+ if (range.end && ts >= range.end.getTime())
+ return false;
+ return true;
+ }).length;
+ }
+
+ readonly property var allFilters: [
+ {
+ label: I18n.tr("All", "notification history filter"),
+ key: "all",
+ maxDays: 0
+ },
+ {
+ label: I18n.tr("Last hour", "notification history filter"),
+ key: "1h",
+ maxDays: 1
+ },
+ {
+ label: I18n.tr("Today", "notification history filter"),
+ key: "today",
+ maxDays: 1
+ },
+ {
+ label: I18n.tr("Yesterday", "notification history filter"),
+ key: "yesterday",
+ maxDays: 2
+ },
+ {
+ label: I18n.tr("7 days", "notification history filter"),
+ key: "7d",
+ maxDays: 7
+ },
+ {
+ label: I18n.tr("30 days", "notification history filter"),
+ key: "30d",
+ maxDays: 30
+ },
+ {
+ label: I18n.tr("Older", "notification history filter for content older than other filters"),
+ key: "older",
+ maxDays: 0
+ }
+ ]
+
+ function filterRelevantForRetention(filter) {
+ const retention = SettingsData.notificationHistoryMaxAgeDays;
+ if (filter.key === "older") {
+ if (retention === 0)
+ return true;
+ return retention > 2 && retention < 7 || retention > 30;
+ }
+ if (retention === 0)
+ return true;
+ if (filter.maxDays === 0)
+ return true;
+ return filter.maxDays <= retention;
+ }
+
+ function getOlderCutoff() {
+ const retention = SettingsData.notificationHistoryMaxAgeDays;
+ const now = new Date();
+ if (retention === 0 || retention > 30)
+ return new Date(now.getTime() - 30 * 86400000);
+ if (retention >= 7)
+ return new Date(now.getTime() - 7 * 86400000);
+ const startOfToday = getStartOfDay(now);
+ return new Date(startOfToday.getTime() - 86400000);
+ }
+
+ readonly property var visibleFilters: {
+ const result = [];
+ const retention = SettingsData.notificationHistoryMaxAgeDays;
+ for (let i = 0; i < allFilters.length; i++) {
+ const f = allFilters[i];
+ if (!filterRelevantForRetention(f))
+ continue;
+ const count = countForFilter(f.key);
+ if (f.key === "all" || count > 0) {
+ result.push({
+ label: f.label,
+ key: f.key,
+ count: count
+ });
+ }
+ }
+ return result;
+ }
+
+ onVisibleFiltersChanged: {
+ let found = false;
+ for (let i = 0; i < visibleFilters.length; i++) {
+ if (visibleFilters[i].key === selectedFilterKey) {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ selectedFilterKey = "all";
+ }
+
+ function getFilteredHistory() {
+ const range = getFilterRange(selectedFilterKey);
+ if (!range.start && !range.end)
+ return NotificationService.historyList;
+ return NotificationService.historyList.filter(n => {
+ const ts = n.timestamp;
+ if (range.start && ts < range.start.getTime())
+ return false;
+ if (range.end && ts >= range.end.getTime())
+ return false;
+ return true;
+ });
+ }
+
+ function getChipIndex() {
+ for (let i = 0; i < visibleFilters.length; i++) {
+ if (visibleFilters[i].key === selectedFilterKey)
+ return i;
+ }
+ return 0;
+ }
+
+ function enableAutoScroll() {
+ }
+
+ function removeWithScrollPreserve(itemId) {
+ historyListView.savedY = historyListView.contentY;
+ NotificationService.removeFromHistory(itemId);
+ Qt.callLater(() => {
+ historyListView.forceLayout();
+ });
+ }
+
+ Column {
+ anchors.fill: parent
+ spacing: Theme.spacingS
+
+ DankFilterChips {
+ id: filterChips
+ width: parent.width
+ currentIndex: root.getChipIndex()
+ showCounts: true
+ model: root.visibleFilters
+ onSelectionChanged: index => {
+ if (index >= 0 && index < root.visibleFilters.length) {
+ root.selectedFilterKey = root.visibleFilters[index].key;
+ }
+ }
+ }
+
+ DankListView {
+ id: historyListView
+ width: parent.width
+ height: parent.height - filterChips.height - Theme.spacingS
+ clip: true
+ spacing: Theme.spacingS
+ readonly property real horizontalShadowGutter: Theme.snap(Math.max(Theme.spacingXS, 4), 1)
+ readonly property real verticalShadowGutter: Theme.snap(Math.max(Theme.spacingS, 8), 1)
+ readonly property real delegateShadowGutter: Theme.snap(Math.max(Theme.spacingXS, 4), 1)
+ topMargin: verticalShadowGutter
+ bottomMargin: verticalShadowGutter
+
+ model: ScriptModel {
+ id: historyModel
+ values: root.getFilteredHistory()
+ objectProp: "id"
+ }
+
+ NotificationEmptyState {
+ visible: historyListView.count === 0
+ y: Theme.spacingL
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+
+ delegate: Item {
+ id: delegateRoot
+ required property var modelData
+ required property int index
+
+ property real swipeOffset: 0
+ property bool isDismissing: false
+ readonly property real dismissThreshold: width * 0.35
+ property bool __delegateInitialized: false
+
+ Component.onCompleted: {
+ Qt.callLater(() => {
+ if (delegateRoot)
+ delegateRoot.__delegateInitialized = true;
+ });
+ }
+
+ width: ListView.view.width
+ height: historyCard.height + historyListView.delegateShadowGutter
+ clip: false
+
+ HistoryNotificationCard {
+ id: historyCard
+ width: Math.max(0, parent.width - (historyListView.horizontalShadowGutter * 2))
+ y: historyListView.delegateShadowGutter / 2
+ x: historyListView.horizontalShadowGutter + delegateRoot.swipeOffset
+ historyItem: modelData
+ isSelected: root.keyboardActive && root.selectedIndex === index
+ keyboardNavigationActive: root.keyboardActive
+ opacity: 1 - Math.abs(delegateRoot.swipeOffset) / (delegateRoot.width * 0.5)
+
+ Behavior on x {
+ enabled: !swipeDragHandler.active && delegateRoot.__delegateInitialized
+ NumberAnimation {
+ duration: Theme.notificationExitDuration
+ easing.type: Theme.standardEasing
+ }
+ }
+
+ Behavior on opacity {
+ enabled: delegateRoot.__delegateInitialized
+ NumberAnimation {
+ duration: delegateRoot.__delegateInitialized ? Theme.notificationExitDuration : 0
+ }
+ }
+ }
+
+ DragHandler {
+ id: swipeDragHandler
+ target: null
+ yAxis.enabled: false
+ xAxis.enabled: true
+
+ onActiveChanged: {
+ if (active || delegateRoot.isDismissing)
+ return;
+ if (Math.abs(delegateRoot.swipeOffset) > delegateRoot.dismissThreshold) {
+ delegateRoot.isDismissing = true;
+ root.removeWithScrollPreserve(delegateRoot.modelData?.id || "");
+ } else {
+ delegateRoot.swipeOffset = 0;
+ }
+ }
+
+ onTranslationChanged: {
+ if (delegateRoot.isDismissing)
+ return;
+ delegateRoot.swipeOffset = translation.x;
+ }
+ }
+ }
+ }
+ }
+
+ function selectNext() {
+ if (historyModel.values.length === 0)
+ return;
+ keyboardActive = true;
+ selectedIndex = Math.min(selectedIndex + 1, historyModel.values.length - 1);
+ historyListView.positionViewAtIndex(selectedIndex, ListView.Contain);
+ }
+
+ function selectPrevious() {
+ if (historyModel.values.length === 0)
+ return;
+ if (selectedIndex <= 0) {
+ keyboardActive = false;
+ selectedIndex = -1;
+ return;
+ }
+ selectedIndex = Math.max(selectedIndex - 1, 0);
+ historyListView.positionViewAtIndex(selectedIndex, ListView.Contain);
+ }
+
+ function clearSelected() {
+ if (selectedIndex < 0 || selectedIndex >= historyModel.values.length)
+ return;
+ const item = historyModel.values[selectedIndex];
+ NotificationService.removeFromHistory(item.id);
+ if (historyModel.values.length === 0) {
+ keyboardActive = false;
+ selectedIndex = -1;
+ } else {
+ selectedIndex = Math.min(selectedIndex, historyModel.values.length - 1);
+ }
+ }
+
+ function handleKey(event) {
+ if (event.key === Qt.Key_Down || event.key === 16777237) {
+ if (!keyboardActive) {
+ keyboardActive = true;
+ selectedIndex = 0;
+ } else {
+ selectNext();
+ }
+ event.accepted = true;
+ } else if (event.key === Qt.Key_Up || event.key === 16777235) {
+ if (keyboardActive) {
+ selectPrevious();
+ }
+ event.accepted = true;
+ } else if (keyboardActive && (event.key === Qt.Key_Delete || event.key === Qt.Key_Backspace)) {
+ clearSelected();
+ event.accepted = true;
+ } else if ((event.key === Qt.Key_Delete || event.key === Qt.Key_Backspace) && (event.modifiers & Qt.ShiftModifier)) {
+ NotificationService.clearHistory();
+ keyboardActive = false;
+ selectedIndex = -1;
+ event.accepted = true;
+ } else if (event.key === Qt.Key_F10) {
+ showKeyboardHints = !showKeyboardHints;
+ event.accepted = true;
+ }
+ }
+}