forked from Shinonome/dots-hyprland
add scroll edge fade to some scrolled windows
This commit is contained in:
@@ -88,7 +88,7 @@ Item {
|
|||||||
delegate: StyledText {
|
delegate: StyledText {
|
||||||
required property string modelData
|
required property string modelData
|
||||||
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent?.horizontalCenter
|
||||||
font {
|
font {
|
||||||
pixelSize: modelData.match(/am|pm/i) ? 26 : 68
|
pixelSize: modelData.match(/am|pm/i) ? 26 : 68
|
||||||
family: Appearance.font.family.expressive
|
family: Appearance.font.family.expressive
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import qs.services
|
|||||||
import qs.modules.common.functions
|
import qs.modules.common.functions
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
|
import Qt5Compat.GraphicalEffects
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Hyprland
|
import Quickshell.Hyprland
|
||||||
import Quickshell.Services.Notifications
|
import Quickshell.Services.Notifications
|
||||||
@@ -220,91 +221,110 @@ Item { // Notification item area
|
|||||||
PointingHandLinkHover {}
|
PointingHandLinkHover {}
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledFlickable { // Notification actions
|
Item {
|
||||||
id: actionsFlickable
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
implicitHeight: actionRowLayout.implicitHeight
|
implicitWidth: actionsFlickable.implicitWidth
|
||||||
contentWidth: actionRowLayout.implicitWidth
|
implicitHeight: actionsFlickable.implicitHeight
|
||||||
clip: !onlyNotification
|
|
||||||
|
|
||||||
Behavior on opacity {
|
layer.enabled: true
|
||||||
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
|
layer.effect: OpacityMask {
|
||||||
}
|
maskSource: Rectangle {
|
||||||
Behavior on height {
|
width: actionsFlickable.width
|
||||||
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
|
height: actionsFlickable.height
|
||||||
}
|
radius: Appearance.rounding.small
|
||||||
Behavior on implicitHeight {
|
}
|
||||||
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
ScrollEdgeFade {
|
||||||
id: actionRowLayout
|
target: actionsFlickable
|
||||||
Layout.alignment: Qt.AlignBottom
|
vertical: false
|
||||||
|
}
|
||||||
|
|
||||||
NotificationActionButton {
|
StyledFlickable { // Notification actions
|
||||||
Layout.fillWidth: true
|
id: actionsFlickable
|
||||||
buttonText: Translation.tr("Close")
|
anchors.fill: parent
|
||||||
urgency: notificationObject.urgency
|
implicitHeight: actionRowLayout.implicitHeight
|
||||||
implicitWidth: (notificationObject.actions.length == 0) ? ((actionsFlickable.width - actionRowLayout.spacing) / 2) :
|
contentWidth: actionRowLayout.implicitWidth
|
||||||
(contentItem.implicitWidth + leftPadding + rightPadding)
|
|
||||||
|
|
||||||
onClicked: {
|
Behavior on opacity {
|
||||||
root.destroyWithAnimation()
|
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
|
||||||
}
|
}
|
||||||
|
Behavior on height {
|
||||||
contentItem: MaterialSymbol {
|
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
|
||||||
iconSize: Appearance.font.pixelSize.large
|
}
|
||||||
horizontalAlignment: Text.AlignHCenter
|
Behavior on implicitHeight {
|
||||||
color: (notificationObject.urgency == NotificationUrgency.Critical) ?
|
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
|
||||||
Appearance.m3colors.m3onSurfaceVariant : Appearance.m3colors.m3onSurface
|
|
||||||
text: "close"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Repeater {
|
RowLayout {
|
||||||
id: actionRepeater
|
id: actionRowLayout
|
||||||
model: notificationObject.actions
|
Layout.alignment: Qt.AlignBottom
|
||||||
|
|
||||||
NotificationActionButton {
|
NotificationActionButton {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
buttonText: modelData.text
|
buttonText: Translation.tr("Close")
|
||||||
urgency: notificationObject.urgency
|
urgency: notificationObject.urgency
|
||||||
|
implicitWidth: (notificationObject.actions.length == 0) ? ((actionsFlickable.width - actionRowLayout.spacing) / 2) :
|
||||||
|
(contentItem.implicitWidth + leftPadding + rightPadding)
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
Notifications.attemptInvokeAction(notificationObject.notificationId, modelData.identifier);
|
root.destroyWithAnimation()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NotificationActionButton {
|
contentItem: MaterialSymbol {
|
||||||
Layout.fillWidth: true
|
iconSize: Appearance.font.pixelSize.large
|
||||||
urgency: notificationObject.urgency
|
horizontalAlignment: Text.AlignHCenter
|
||||||
implicitWidth: (notificationObject.actions.length == 0) ? ((actionsFlickable.width - actionRowLayout.spacing) / 2) :
|
color: (notificationObject.urgency == NotificationUrgency.Critical) ?
|
||||||
(contentItem.implicitWidth + leftPadding + rightPadding)
|
Appearance.m3colors.m3onSurfaceVariant : Appearance.m3colors.m3onSurface
|
||||||
|
text: "close"
|
||||||
onClicked: {
|
|
||||||
Quickshell.clipboardText = notificationObject.body
|
|
||||||
copyIcon.text = "inventory"
|
|
||||||
copyIconTimer.restart()
|
|
||||||
}
|
|
||||||
|
|
||||||
Timer {
|
|
||||||
id: copyIconTimer
|
|
||||||
interval: 1500
|
|
||||||
repeat: false
|
|
||||||
onTriggered: {
|
|
||||||
copyIcon.text = "content_copy"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contentItem: MaterialSymbol {
|
Repeater {
|
||||||
id: copyIcon
|
id: actionRepeater
|
||||||
iconSize: Appearance.font.pixelSize.large
|
model: notificationObject.actions
|
||||||
horizontalAlignment: Text.AlignHCenter
|
NotificationActionButton {
|
||||||
color: (notificationObject.urgency == NotificationUrgency.Critical) ?
|
Layout.fillWidth: true
|
||||||
Appearance.m3colors.m3onSurfaceVariant : Appearance.m3colors.m3onSurface
|
buttonText: modelData.text
|
||||||
text: "content_copy"
|
urgency: notificationObject.urgency
|
||||||
|
onClicked: {
|
||||||
|
Notifications.attemptInvokeAction(notificationObject.notificationId, modelData.identifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NotificationActionButton {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
urgency: notificationObject.urgency
|
||||||
|
implicitWidth: (notificationObject.actions.length == 0) ? ((actionsFlickable.width - actionRowLayout.spacing) / 2) :
|
||||||
|
(contentItem.implicitWidth + leftPadding + rightPadding)
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
Quickshell.clipboardText = notificationObject.body
|
||||||
|
copyIcon.text = "inventory"
|
||||||
|
copyIconTimer.restart()
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: copyIconTimer
|
||||||
|
interval: 1500
|
||||||
|
repeat: false
|
||||||
|
onTriggered: {
|
||||||
|
copyIcon.text = "content_copy"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contentItem: MaterialSymbol {
|
||||||
|
id: copyIcon
|
||||||
|
iconSize: Appearance.font.pixelSize.large
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
color: (notificationObject.urgency == NotificationUrgency.Critical) ?
|
||||||
|
Appearance.m3colors.m3onSurfaceVariant : Appearance.m3colors.m3onSurface
|
||||||
|
text: "content_copy"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
import QtQuick
|
||||||
|
import qs.modules.common
|
||||||
|
import qs.modules.common.functions
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
z: 99
|
||||||
|
required property Item target
|
||||||
|
property real fadeSize: Appearance.m3colors.darkmode ? 40 : 20
|
||||||
|
property color color: ColorUtils.transparentize(Appearance.colors.colShadow, Appearance.m3colors.darkmode ? 0 : 0.7)
|
||||||
|
property bool vertical: true
|
||||||
|
|
||||||
|
anchors.fill: target
|
||||||
|
|
||||||
|
EndGradient {
|
||||||
|
anchors {
|
||||||
|
top: parent.top
|
||||||
|
left: parent.left
|
||||||
|
right: vertical ? parent.right : undefined
|
||||||
|
bottom: vertical ? undefined : parent.bottom
|
||||||
|
}
|
||||||
|
shown: !(root.vertical ? root.target.atYBeginning : root.target.atXBeginning)
|
||||||
|
}
|
||||||
|
|
||||||
|
EndGradient {
|
||||||
|
anchors {
|
||||||
|
bottom: parent.bottom
|
||||||
|
right: parent.right
|
||||||
|
left: vertical ? parent.left : undefined
|
||||||
|
top: vertical ? undefined : parent.top
|
||||||
|
}
|
||||||
|
shown: !(root.vertical ? root.target.atYEnd : root.target.atXEnd)
|
||||||
|
rotation: 180
|
||||||
|
}
|
||||||
|
|
||||||
|
component EndGradient: Rectangle {
|
||||||
|
required property bool shown
|
||||||
|
height: vertical ? root.fadeSize : parent.height
|
||||||
|
width: vertical ? parent.width : root.fadeSize
|
||||||
|
|
||||||
|
opacity: shown ? 1 : 0
|
||||||
|
visible: opacity > 0
|
||||||
|
Behavior on opacity {
|
||||||
|
animation: Appearance?.animation.elementMoveFast.numberAnimation.createObject(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
gradient: Gradient {
|
||||||
|
orientation: root.vertical ? Gradient.Vertical : Gradient.Horizontal
|
||||||
|
GradientStop {
|
||||||
|
position: 0.0
|
||||||
|
color: root.color
|
||||||
|
}
|
||||||
|
GradientStop {
|
||||||
|
position: 1.0
|
||||||
|
color: ColorUtils.transparentize(root.color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -50,4 +50,5 @@ Flickable {
|
|||||||
root.scrollTargetY = root.contentY;
|
root.scrollTargetY = root.contentY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -308,6 +308,20 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\)
|
|||||||
Item { // Messages
|
Item { // Messages
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
|
layer.enabled: true
|
||||||
|
layer.effect: OpacityMask {
|
||||||
|
maskSource: Rectangle {
|
||||||
|
width: swipeView.width
|
||||||
|
height: swipeView.height
|
||||||
|
radius: Appearance.rounding.small
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrollEdgeFade {
|
||||||
|
target: messageListView
|
||||||
|
vertical: true
|
||||||
|
}
|
||||||
|
|
||||||
StyledListView { // Message list
|
StyledListView { // Message list
|
||||||
id: messageListView
|
id: messageListView
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@@ -318,8 +332,8 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\)
|
|||||||
mouseScrollFactor: Config.options.interactions.scrolling.mouseScrollFactor * 1.4
|
mouseScrollFactor: Config.options.interactions.scrolling.mouseScrollFactor * 1.4
|
||||||
|
|
||||||
property int lastResponseLength: 0
|
property int lastResponseLength: 0
|
||||||
|
|
||||||
property bool shouldAutoScroll: true
|
property bool shouldAutoScroll: true
|
||||||
|
|
||||||
onContentYChanged: shouldAutoScroll = atYEnd
|
onContentYChanged: shouldAutoScroll = atYEnd
|
||||||
onContentHeightChanged: {
|
onContentHeightChanged: {
|
||||||
if (shouldAutoScroll) positionViewAtEnd();
|
if (shouldAutoScroll) positionViewAtEnd();
|
||||||
@@ -328,16 +342,6 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\)
|
|||||||
if (shouldAutoScroll) positionViewAtEnd();
|
if (shouldAutoScroll) positionViewAtEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
clip: true
|
|
||||||
layer.enabled: true
|
|
||||||
layer.effect: OpacityMask {
|
|
||||||
maskSource: Rectangle {
|
|
||||||
width: swipeView.width
|
|
||||||
height: swipeView.height
|
|
||||||
radius: Appearance.rounding.small
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
add: null // Prevent function calls from being janky
|
add: null // Prevent function calls from being janky
|
||||||
|
|
||||||
model: ScriptModel {
|
model: ScriptModel {
|
||||||
|
|||||||
@@ -141,6 +141,21 @@ Item {
|
|||||||
Item {
|
Item {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
|
|
||||||
|
layer.enabled: true
|
||||||
|
layer.effect: OpacityMask {
|
||||||
|
maskSource: Rectangle {
|
||||||
|
width: swipeView.width
|
||||||
|
height: swipeView.height
|
||||||
|
radius: Appearance.rounding.small
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrollEdgeFade {
|
||||||
|
target: booruResponseListView
|
||||||
|
vertical: true
|
||||||
|
}
|
||||||
|
|
||||||
StyledListView { // Booru responses
|
StyledListView { // Booru responses
|
||||||
id: booruResponseListView
|
id: booruResponseListView
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@@ -151,16 +166,6 @@ Item {
|
|||||||
|
|
||||||
property int lastResponseLength: 0
|
property int lastResponseLength: 0
|
||||||
|
|
||||||
clip: true
|
|
||||||
layer.enabled: true
|
|
||||||
layer.effect: OpacityMask {
|
|
||||||
maskSource: Rectangle {
|
|
||||||
width: swipeView.width
|
|
||||||
height: swipeView.height
|
|
||||||
radius: Appearance.rounding.small
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
model: ScriptModel {
|
model: ScriptModel {
|
||||||
values: {
|
values: {
|
||||||
if(root.responses.length > booruResponseListView.lastResponseLength) {
|
if(root.responses.length > booruResponseListView.lastResponseLength) {
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ Item {
|
|||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
Flickable {
|
StyledFlickable {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
contentHeight: contentColumn.implicitHeight
|
contentHeight: contentColumn.implicitHeight
|
||||||
|
|||||||
@@ -105,7 +105,6 @@ Rectangle {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
implicitHeight: tagRowLayout.implicitHeight
|
implicitHeight: tagRowLayout.implicitHeight
|
||||||
// height: tagRowLayout.implicitHeight
|
|
||||||
contentWidth: tagRowLayout.implicitWidth
|
contentWidth: tagRowLayout.implicitWidth
|
||||||
|
|
||||||
clip: true
|
clip: true
|
||||||
@@ -118,9 +117,6 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior on height {
|
|
||||||
animation: Appearance.animation.elementMove.numberAnimation.createObject(this)
|
|
||||||
}
|
|
||||||
Behavior on implicitHeight {
|
Behavior on implicitHeight {
|
||||||
animation: Appearance.animation.elementMove.numberAnimation.createObject(this)
|
animation: Appearance.animation.elementMove.numberAnimation.createObject(this)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user