shift-shell/shell/contents/lockscreen/QuickActionButton.qml

143 lines
4.4 KiB
QML
Raw Normal View History

// SPDX-FileCopyrightText: 2025 User8395 <therealuser8395@proton.me>
// SPDX-License-Identifier: GPL-2.0-or-later
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import org.kde.plasma.quicksetting.flashlight
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
import org.kde.kirigami as Kirigami
AbstractButton {
id: root
property int buttonAction
property bool buttonHeld: false
property double scale: pressed ? (buttonHeld ? heldScale : pressedScale) : 1
property real fillAmount: 0.0
readonly property int visualAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.Standard)
readonly property real pressedScale: MobileShell.Motion.pressScaleOut
readonly property real heldScale: MobileShell.Motion.enabled ? 1.14 : 1
readonly property color actionSurfaceColor: Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, 0.16)
readonly property color actionFillColor: Qt.rgba(Kirigami.Theme.highlightColor.r, Kirigami.Theme.highlightColor.g, Kirigami.Theme.highlightColor.b, 0.32)
Behavior on scale {
MobileShell.MotionNumberAnimation {
type: MobileShell.Motion.Standard
duration: root.visualAnimationDuration
}
}
MobileShell.HapticsEffect {
id: haptics
}
visible: buttonAction !== ShellSettings.Settings.None
padding: Math.round(Kirigami.Units.gridUnit * 1.25)
transform: Scale {
origin.x: width / 2
origin.y: height / 2
xScale: scale
yScale: scale
}
background: Rectangle {
radius: width
color: root.actionSurfaceColor
Rectangle {
anchors.centerIn: parent
width: parent.width * root.fillAmount
height: parent.height * root.fillAmount
radius: Math.min(width, height)
color: root.actionFillColor
}
}
contentItem: Item {
Kirigami.Icon {
anchors.centerIn: parent
width: Kirigami.Units.iconSizes.small
height: Kirigami.Units.iconSizes.small
source: {
switch (buttonAction) {
case ShellSettings.Settings.Flashlight:
return "flashlight-on-symbolic"
case ShellSettings.Settings.Camera:
return "camera-photo-symbolic"
}
}
Kirigami.Theme.inherit: false
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
}
}
onPressedChanged: {
if (pressed) {
pressedTimer.restart();
buttonHeld = false;
// Ensure emptyAnimation is not running
// And fillAnimation use current fillAmount state before start
// To avoid "reset" glitch
emptyAnimation.stop();
fillAnimation.from = root.fillAmount;
fillAnimation.start();
} else {
pressedTimer.stop();
// Ensure fillAnimation is not running
// And emptyAnimation use current fillAmount state before start
// To avoid "reset" glitch
fillAnimation.stop();
emptyAnimation.from = root.fillAmount;
emptyAnimation.start();
}
}
function triggerButtonAction() {
switch (buttonAction) {
case ShellSettings.Settings.Flashlight:
FlashlightUtil.toggleTorch();
return;
case ShellSettings.Settings.Camera:
MobileShell.ShellUtil.launchApp("org.kde.plasma.camera");
flickable.goToOpenPosition();
return;
}
}
Timer {
id: pressedTimer
interval: Kirigami.Units.longDuration
repeat: false
onTriggered: {
haptics.buttonVibrate();
buttonHeld = true;
triggerButtonAction();
}
}
MobileShell.MotionNumberAnimation {
id: fillAnimation
target: root
property: "fillAmount"
type: MobileShell.Motion.Standard
duration: root.visualAnimationDuration
to: 1.0
}
MobileShell.MotionNumberAnimation {
id: emptyAnimation
target: root
property: "fillAmount"
type: MobileShell.Motion.Standard
duration: root.visualAnimationDuration
to: 0.0
}
}