shift-shell/components/mobileshell/qml/actiondrawer/PortraitContentContainer.qml
Micah Stanley 600fd05900 actiondrawer: Added the Over-Scroll Effect to all Portrait Mode Quick Settings States
Brought the over-scroll effect found in the pinned quick settings panel to all the portrait mode quick settings states.
This helps improve the user experience while also bringing more consistency when pulling down the panel.

![over-scroll](/uploads/a8531b6fb51fde6fc7dc9c9647945899/over-scroll.gif)
2024-06-22 04:50:09 +00:00

130 lines
5.5 KiB
QML

/*
* SPDX-FileCopyrightText: 2021 Devin Lin <devin@kde.org>
*
* SPDX-License-Identifier: LGPL-2.0-or-later
*/
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.1
import QtQuick.Window 2.2
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.kirigami 2.20 as Kirigami
/**
* Root element that contains all the ActionDrawer's contents, and is anchored to the screen.
*/
Item {
id: root
required property var actionDrawer
property alias notificationsWidget: notificationWidget
// pinned position (disabled when openToPinnedMode is false)
readonly property real minimizedQuickSettingsOffset: quickSettings.minimizedHeight
// fully open position
readonly property real maximizedQuickSettingsOffset: minimizedQuickSettingsOffset + quickSettings.maxAddedHeight
Kirigami.Theme.colorSet: Kirigami.Theme.View
Kirigami.Theme.inherit: false
function applyMinMax(val) {
return Math.max(0, Math.min(1, val));
}
// fullscreen background
Rectangle {
anchors.fill: parent
// darken if there are notifications
color: Qt.rgba(Kirigami.Theme.backgroundColor.r,
Kirigami.Theme.backgroundColor.g,
Kirigami.Theme.backgroundColor.b,
0.95)
Behavior on color { ColorAnimation { duration: Kirigami.Units.longDuration } }
opacity: Math.max(0, Math.min(1, actionDrawer.offset / root.minimizedQuickSettingsOffset))
}
MobileShell.QuickSettingsDrawer {
id: quickSettings
z: 1 // ensure it's above notifications
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
actionDrawer: root.actionDrawer
// opacity and move animation (disabled when openToPinnedMode is false)
property real offsetDist: actionDrawer.offset - minimizedQuickSettingsOffset
property real totalOffsetDist: maximizedQuickSettingsOffset - minimizedQuickSettingsOffset
minimizedToFullProgress: actionDrawer.openToPinnedMode ? (actionDrawer.opened ? applyMinMax(offsetDist / totalOffsetDist) : 0) : 1
// this drawer opens in two stages when pinned mode is enabled:
// ---
// stage 1: the transform effect is used, the drawer physically moves down to the pinned mode
// stage 2: the rectangle increases height to reveal content, but the content stays still
// when pinned mode is disabled, only stage 1 happens
// increase height of drawer when between pinned mode <-> maximized mode
addedHeight: {
if (!actionDrawer.openToPinnedMode) {
// if pinned mode disabled, just go to full height
let progress = (root.actionDrawer.offset - maximizedQuickSettingsOffset) / (quickSettings.maxAddedHeight * 4);
let effectProgress = Math.atan(Math.max(0, progress));
return (quickSettings.maxAddedHeight * effectProgress) + quickSettings.maxAddedHeight;
} else if (!actionDrawer.opened) {
// over-scroll effect for initial opening
let progress = (root.actionDrawer.offset - minimizedQuickSettingsOffset) / quickSettings.maxAddedHeight;
let effectProgress = Math.atan(Math.max(0, progress));
return quickSettings.maxAddedHeight * 0.25 * effectProgress;
} else {
// over-scroll effect for full drawer
let progress = (root.actionDrawer.offset - maximizedQuickSettingsOffset) / (quickSettings.maxAddedHeight * 4);
let effectProgress = Math.atan(Math.max(0, progress));
// as the drawer opens, add height to the rectangle, revealing content
return (quickSettings.maxAddedHeight * effectProgress) + Math.max(0, Math.min(quickSettings.maxAddedHeight, root.actionDrawer.offset - minimizedQuickSettingsOffset));
}
}
// physically move the drawer when between closed <-> pinned mode
transform: Translate {
id: translate
readonly property real offsetHeight: actionDrawer.openToPinnedMode ? minimizedQuickSettingsOffset : maximizedQuickSettingsOffset
y: Math.min(root.actionDrawer.offset - offsetHeight, 0)
}
}
MobileShell.NotificationsWidget {
id: notificationWidget
historyModel: root.actionDrawer.notificationModel
historyModelType: root.actionDrawer.notificationModelType
notificationSettings: root.actionDrawer.notificationSettings
actionsRequireUnlock: root.actionDrawer.restrictedPermissions
onUnlockRequested: root.actionDrawer.permissionsRequested()
Connections {
target: root.actionDrawer
function onRunPendingNotificationAction() {
notificationWidget.runPendingAction();
}
}
onBackgroundClicked: root.actionDrawer.close();
anchors {
top: quickSettings.top
topMargin: quickSettings.height + translate.y
bottom: parent.bottom
left: parent.left
right: parent.right
}
opacity: applyMinMax(root.actionDrawer.offset / root.minimizedQuickSettingsOffset)
// HACK: there are weird issues with text rendering black regardless of opacity, just set the text to be invisible once it's out
visible: opacity > 0.05
}
}