shift-shell/containments/homescreens/halcyon/qml/FavoritesView.qml
Marco Allegretti a37734b74a Move homescreens to shared motion
Use Motion wrappers and state layers across Folio and Halcyon delegates, drawers, folders, resize handles, and dock feedback. Also align Folio edit/drop highlights with theme colors instead of fixed white overlays.
2026-05-21 11:13:36 +02:00

209 lines
5.8 KiB
QML

// SPDX-FileCopyrightText: 2022 Devin Lin <devin@kde.org>
// SPDX-License-Identifier: LGPL-2.0-or-later
import QtQuick 2.12
import QtQuick.Controls 2.15 as QQC2
import QtQuick.Layouts 1.1
import QtQml.Models 2.15
import org.kde.plasma.components 3.0 as PC3
import org.kde.draganddrop 2.0 as DragDrop
import org.kde.kirigami as Kirigami
import org.kde.plasma.private.mobileshell as MobileShell
Item {
id: root
layer.enabled: true
property MobileShell.MaskManager maskManager
required property bool interactive
required property var searchWidget
readonly property real twoColumnThreshold: Kirigami.Units.gridUnit * 16
readonly property bool twoColumn: root.width / 2 > twoColumnThreshold
readonly property real cellWidth: twoColumn ? (root.width - leftMargin - rightMargin) / 2 : (root.width - leftMargin - rightMargin)
readonly property real cellHeight: delegateHeight
readonly property int longAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.SpatialDefault)
readonly property real leftMargin: Math.round(width * 0.1)
readonly property real rightMargin: Math.round(width * 0.1)
readonly property real delegateHeight: Math.round(Kirigami.Units.gridUnit * 3)
property bool folderShown: false
signal openConfigureRequested()
signal pageForwardRequested();
Connections {
target: parent
function onFocusRequested() {
favoritesGrid.forceActiveFocus();
}
}
function goToBeginning() {
goToBeginningAnim.restart();
}
function closeFolder() {
folderShown = false;
closeFolderAnim.restart()
}
function openFolder() {
folderShown = true;
openFolderAnim.restart()
}
function resetHighlight() {
favoritesGrid.currentIndex = -1;
}
FavoritesGrid {
id: favoritesGrid
property real openFolderProgress: 0
anchors.fill: parent
maskManager: root.maskManager
interactive: root.interactive
searchWidget: root.searchWidget
cellWidth: root.cellWidth
cellHeight: root.cellHeight
leftMargin: root.leftMargin
rightMargin: root.rightMargin
twoColumn: root.twoColumn
onOpenConfigureRequested: root.openConfigureRequested()
onRequestOpenFolder: (folder) => {
folderGrid.folder = folder;
root.openFolder();
}
property real translateX: openFolderProgress * -Kirigami.Units.gridUnit
transform: Translate { x: favoritesGrid.translateX }
opacity: 1 - openFolderProgress
visible: opacity !== 0
rightEdgeCallback: () => {
pageForwardRequested();
}
}
FolderGrid {
id: folderGrid
property real openProgress: 0
anchors.fill: parent
folder: null
interactive: root.interactive
cellWidth: root.cellWidth
cellHeight: root.cellHeight
leftMargin: root.leftMargin
rightMargin: root.rightMargin
twoColumn: root.twoColumn
onOpenConfigureRequested: root.openConfigureRequested()
onCloseRequested: root.closeFolder()
property real translateX: (1 - openProgress) * Kirigami.Units.gridUnit
transform: Translate { x: folderGrid.translateX }
opacity: openProgress
visible: opacity !== 0
}
// handle horizontal dragging in a folder
DragHandler {
id: dragHandler
target: folderGrid
enabled: folderGrid.visible
yAxis.enabled: false
xAxis.enabled: true
grabPermissions: PointerHandler.TakeOverForbidden
property real oldTranslationX
property bool isClosing: false
// when dragged
onTranslationChanged: {
let moveAmount = Math.max(0, translation.x) / (Kirigami.Units.gridUnit * 5);
folderGrid.openProgress = 1 - Math.min(1, Math.max(0, moveAmount));
isClosing = translation.x > oldTranslationX;
oldTranslationX = translation.x;
}
// when drag is let go
onActiveChanged: {
if (!active) {
isClosing ? closeFolder() : openFolder();
}
}
}
MobileShell.MotionNumberAnimation {
id: goToBeginningAnim
target: favoritesGrid
properties: 'contentY'
to: favoritesGrid.originY
type: MobileShell.Motion.SpatialDefault
duration: root.longAnimationDuration
}
SequentialAnimation {
id: openFolderAnim
ParallelAnimation {
MobileShell.MotionNumberAnimation {
target: favoritesGrid
properties: 'openFolderProgress'
type: MobileShell.Motion.SpatialDefault
duration: root.longAnimationDuration
to: 1
}
}
ParallelAnimation {
MobileShell.MotionNumberAnimation {
target: folderGrid
properties: 'openProgress'
type: MobileShell.Motion.SpatialDefault
duration: root.longAnimationDuration
to: 1
}
}
}
SequentialAnimation {
id: closeFolderAnim
ParallelAnimation {
MobileShell.MotionNumberAnimation {
target: folderGrid
properties: 'openProgress'
type: MobileShell.Motion.SpatialDefault
duration: root.longAnimationDuration
to: 0
}
}
ParallelAnimation {
MobileShell.MotionNumberAnimation {
target: favoritesGrid
properties: 'openFolderProgress'
type: MobileShell.Motion.SpatialDefault
duration: root.longAnimationDuration
to: 0
}
}
}
}