summaryrefslogtreecommitdiff
path: root/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Notifications/Center/KeyboardNavigatedNotificationList.qml
diff options
context:
space:
mode:
authorAlexanderCurl <alexc@alexc.hu>2026-04-18 17:46:06 +0100
committerAlexanderCurl <alexc@alexc.hu>2026-04-18 17:46:06 +0100
commit70ca3fef77ee8bdc6e3ac28589a6fa08c024cc69 (patch)
treeab1123d4067c1b086dd6faa7ee4ea643236b565a /raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Notifications/Center/KeyboardNavigatedNotificationList.qml
parent5d94c0a7d44a2255b81815a52a7056a94a39842d (diff)
downloadRaveOS-PKGBUILD-70ca3fef77ee8bdc6e3ac28589a6fa08c024cc69.tar.gz
RaveOS-PKGBUILD-70ca3fef77ee8bdc6e3ac28589a6fa08c024cc69.zip
Replaced file structures for themes in the correct format
Diffstat (limited to 'raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Notifications/Center/KeyboardNavigatedNotificationList.qml')
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Notifications/Center/KeyboardNavigatedNotificationList.qml311
1 files changed, 311 insertions, 0 deletions
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Notifications/Center/KeyboardNavigatedNotificationList.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Notifications/Center/KeyboardNavigatedNotificationList.qml
new file mode 100644
index 0000000..855163d
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Notifications/Center/KeyboardNavigatedNotificationList.qml
@@ -0,0 +1,311 @@
+import QtQuick
+import qs.Common
+import qs.Services
+import qs.Widgets
+
+DankListView {
+ id: listView
+
+ property var keyboardController: null
+ property bool keyboardActive: false
+ property bool autoScrollDisabled: false
+ property bool isAnimatingExpansion: false
+ property alias listContentHeight: listView.contentHeight
+ property real stableContentHeight: 0
+ property bool cardAnimateExpansion: true
+ property bool listInitialized: false
+ property int swipingCardIndex: -1
+ property real swipingCardOffset: 0
+ property real __pendingStableHeight: 0
+ property real __heightUpdateThreshold: 20
+ readonly property real shadowBlurPx: Theme.elevationEnabled ? ((Theme.elevationLevel1 && Theme.elevationLevel1.blurPx !== undefined) ? Theme.elevationLevel1.blurPx : 4) : 0
+ readonly property real shadowHorizontalGutter: Theme.snap(Math.max(Theme.spacingS, Math.min(32, shadowBlurPx * 1.5 + 6)), 1)
+ readonly property real shadowVerticalGutter: Theme.snap(Math.max(Theme.spacingXS, 6), 1)
+ readonly property real delegateShadowGutter: Theme.snap(Math.max(Theme.spacingXS, 4), 1)
+
+ Component.onCompleted: {
+ Qt.callLater(() => {
+ if (listView) {
+ listView.listInitialized = true;
+ listView.stableContentHeight = listView.contentHeight;
+ }
+ });
+ }
+
+ Timer {
+ id: heightUpdateDebounce
+ interval: Theme.mediumDuration + 20
+ repeat: false
+ onTriggered: {
+ if (!listView.isAnimatingExpansion && Math.abs(listView.__pendingStableHeight - listView.stableContentHeight) > listView.__heightUpdateThreshold) {
+ listView.stableContentHeight = listView.__pendingStableHeight;
+ }
+ }
+ }
+
+ onContentHeightChanged: {
+ if (!isAnimatingExpansion) {
+ __pendingStableHeight = contentHeight;
+ if (Math.abs(contentHeight - stableContentHeight) > __heightUpdateThreshold) {
+ heightUpdateDebounce.restart();
+ } else {
+ stableContentHeight = contentHeight;
+ }
+ }
+ }
+
+ onIsAnimatingExpansionChanged: {
+ if (isAnimatingExpansion) {
+ heightUpdateDebounce.stop();
+ let delta = 0;
+ for (let i = 0; i < count; i++) {
+ const item = itemAtIndex(i);
+ if (item && item.children[0] && item.children[0].isAnimating) {
+ const targetDelegateHeight = item.children[0].targetHeight + listView.delegateShadowGutter;
+ delta += targetDelegateHeight - item.height;
+ }
+ }
+ const targetHeight = contentHeight + delta;
+ // During expansion, always update immediately without threshold check
+ stableContentHeight = targetHeight;
+ } else {
+ __pendingStableHeight = contentHeight;
+ heightUpdateDebounce.stop();
+ stableContentHeight = __pendingStableHeight;
+ }
+ }
+
+ clip: true
+ model: NotificationService.groupedNotifications
+ spacing: Theme.spacingL
+ topMargin: shadowVerticalGutter
+ bottomMargin: shadowVerticalGutter
+
+ onIsUserScrollingChanged: {
+ if (isUserScrolling && keyboardController && keyboardController.keyboardNavigationActive) {
+ autoScrollDisabled = true;
+ }
+ }
+
+ function enableAutoScroll() {
+ autoScrollDisabled = false;
+ }
+
+ Timer {
+ id: positionPreservationTimer
+ interval: 200
+ running: keyboardController && keyboardController.keyboardNavigationActive && !autoScrollDisabled && !isAnimatingExpansion
+ repeat: true
+ onTriggered: {
+ if (keyboardController && keyboardController.keyboardNavigationActive && !autoScrollDisabled && !isAnimatingExpansion) {
+ keyboardController.ensureVisible();
+ }
+ }
+ }
+
+ Timer {
+ id: expansionEnsureVisibleTimer
+ interval: Theme.mediumDuration + 50
+ repeat: false
+ onTriggered: {
+ if (keyboardController && keyboardController.keyboardNavigationActive && !autoScrollDisabled) {
+ keyboardController.ensureVisible();
+ }
+ }
+ }
+
+ NotificationEmptyState {
+ visible: listView.count === 0
+ y: 20
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+
+ onModelChanged: {
+ if (!keyboardController || !keyboardController.keyboardNavigationActive) {
+ return;
+ }
+ keyboardController.rebuildFlatNavigation();
+ Qt.callLater(() => {
+ if (keyboardController && keyboardController.keyboardNavigationActive && !autoScrollDisabled) {
+ keyboardController.ensureVisible();
+ }
+ });
+ }
+
+ delegate: Item {
+ id: delegateRoot
+ required property var modelData
+ required property int index
+
+ readonly property bool isExpanded: (NotificationService.expandedGroups[modelData && modelData.key] || false)
+ property real swipeOffset: 0
+ property bool isDismissing: false
+ readonly property real dismissThreshold: width * 0.35
+ property bool __delegateInitialized: false
+
+ readonly property bool isAdjacentToSwipe: listView.count >= 2 && listView.swipingCardIndex !== -1 && (index === listView.swipingCardIndex - 1 || index === listView.swipingCardIndex + 1)
+ readonly property real adjacentSwipeInfluence: isAdjacentToSwipe ? listView.swipingCardOffset * 0.10 : 0
+ readonly property real adjacentScaleInfluence: isAdjacentToSwipe ? 1.0 - Math.abs(listView.swipingCardOffset) / width * 0.02 : 1.0
+ readonly property real swipeFadeStartOffset: width * 0.75
+ readonly property real swipeFadeDistance: Math.max(1, width - swipeFadeStartOffset)
+
+ Component.onCompleted: {
+ Qt.callLater(() => {
+ if (delegateRoot)
+ delegateRoot.__delegateInitialized = true;
+ });
+ }
+
+ width: ListView.view.width
+ height: notificationCard.height + listView.delegateShadowGutter
+ clip: false
+
+ NotificationCard {
+ id: notificationCard
+ width: Math.max(0, parent.width - (listView.shadowHorizontalGutter * 2))
+ y: listView.delegateShadowGutter / 2
+ x: listView.shadowHorizontalGutter + delegateRoot.swipeOffset + delegateRoot.adjacentSwipeInfluence
+ listLevelAdjacentScaleInfluence: delegateRoot.adjacentScaleInfluence
+ listLevelScaleAnimationsEnabled: listView.swipingCardIndex === -1 || !delegateRoot.isAdjacentToSwipe
+ notificationGroup: modelData
+ keyboardNavigationActive: listView.keyboardActive
+ animateExpansion: listView.cardAnimateExpansion && listView.listInitialized
+ opacity: {
+ const swipeAmount = Math.abs(delegateRoot.swipeOffset);
+ if (swipeAmount <= delegateRoot.swipeFadeStartOffset)
+ return 1;
+ const fadeProgress = (swipeAmount - delegateRoot.swipeFadeStartOffset) / delegateRoot.swipeFadeDistance;
+ return Math.max(0, 1 - fadeProgress);
+ }
+ onIsAnimatingChanged: {
+ if (isAnimating) {
+ listView.isAnimatingExpansion = true;
+ } else {
+ Qt.callLater(() => {
+ if (!notificationCard || !listView)
+ return;
+ let anyAnimating = false;
+ for (let i = 0; i < listView.count; i++) {
+ const item = listView.itemAtIndex(i);
+ if (item && item.children[0] && item.children[0].isAnimating) {
+ anyAnimating = true;
+ break;
+ }
+ }
+ listView.isAnimatingExpansion = anyAnimating;
+ });
+ }
+ }
+
+ isGroupSelected: {
+ if (!keyboardController || !keyboardController.keyboardNavigationActive || !listView.keyboardActive)
+ return false;
+ keyboardController.selectionVersion;
+ const selection = keyboardController.getCurrentSelection();
+ return selection.type === "group" && selection.groupIndex === index;
+ }
+
+ selectedNotificationIndex: {
+ if (!keyboardController || !keyboardController.keyboardNavigationActive || !listView.keyboardActive)
+ return -1;
+ keyboardController.selectionVersion;
+ const selection = keyboardController.getCurrentSelection();
+ return (selection.type === "notification" && selection.groupIndex === index) ? selection.notificationIndex : -1;
+ }
+
+ Behavior on x {
+ enabled: !swipeDragHandler.active && !delegateRoot.isDismissing && (listView.swipingCardIndex === -1 || !delegateRoot.isAdjacentToSwipe) && listView.listInitialized
+ NumberAnimation {
+ duration: Theme.shortDuration
+ easing.type: Theme.standardEasing
+ }
+ }
+
+ Behavior on opacity {
+ enabled: listView.listInitialized
+ NumberAnimation {
+ duration: listView.listInitialized ? Theme.shortDuration : 0
+ }
+ }
+ }
+
+ DragHandler {
+ id: swipeDragHandler
+ target: null
+ yAxis.enabled: false
+ xAxis.enabled: true
+
+ onActiveChanged: {
+ if (active) {
+ listView.swipingCardIndex = index;
+ return;
+ }
+ listView.swipingCardIndex = -1;
+ listView.swipingCardOffset = 0;
+ if (delegateRoot.isDismissing)
+ return;
+ if (Math.abs(delegateRoot.swipeOffset) > delegateRoot.dismissThreshold) {
+ delegateRoot.isDismissing = true;
+ swipeDismissAnim.to = delegateRoot.swipeOffset > 0 ? delegateRoot.width : -delegateRoot.width;
+ swipeDismissAnim.start();
+ } else {
+ delegateRoot.swipeOffset = 0;
+ }
+ }
+
+ onTranslationChanged: {
+ if (delegateRoot.isDismissing)
+ return;
+ delegateRoot.swipeOffset = translation.x;
+ listView.swipingCardOffset = translation.x;
+ }
+ }
+
+ NumberAnimation {
+ id: swipeDismissAnim
+ target: delegateRoot
+ property: "swipeOffset"
+ to: 0
+ duration: Theme.notificationExitDuration
+ easing.type: Easing.OutCubic
+ onStopped: NotificationService.dismissGroup(delegateRoot.modelData?.key || "")
+ }
+ }
+
+ Connections {
+ target: NotificationService
+
+ function onGroupedNotificationsChanged() {
+ if (!keyboardController) {
+ return;
+ }
+
+ if (keyboardController.isTogglingGroup) {
+ keyboardController.rebuildFlatNavigation();
+ return;
+ }
+
+ keyboardController.rebuildFlatNavigation();
+
+ if (keyboardController.keyboardNavigationActive) {
+ Qt.callLater(() => {
+ if (!autoScrollDisabled) {
+ keyboardController.ensureVisible();
+ }
+ });
+ }
+ }
+
+ function onExpandedGroupsChanged() {
+ if (!keyboardController || !keyboardController.keyboardNavigationActive)
+ return;
+ expansionEnsureVisibleTimer.restart();
+ }
+
+ function onExpandedMessagesChanged() {
+ if (!keyboardController || !keyboardController.keyboardNavigationActive)
+ return;
+ expansionEnsureVisibleTimer.restart();
+ }
+ }
+}