shift-shell/initialstart/qml/LandingComponent.qml
Marco Allegretti 753909a6ce Move shell and KWin surfaces to shared motion
Apply Motion tokens to startup, applet configuration, lockscreen controls, logout and splash transitions, KWin effects, and the mobile task switcher. Preserve timing-specific behavior where it drives runtime state.
2026-05-21 11:14:42 +02:00

165 lines
4.9 KiB
QML

// SPDX-FileCopyrightText: 2023 Devin Lin <devin@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
import QtCore
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import org.kde.kirigami as Kirigami
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.mobileinitialstart.initialstart
import org.kde.plasma.mobileinitialstart.prepare 1.0 as Prepare
Item {
id: root
readonly property real scaleStart: 1.16
readonly property real scaleLanding: 1.08
readonly property real scaleSteps: 1
readonly property int initialContentFadeDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsSlow) * 2
readonly property int returnContentFadeDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsDefault)
readonly property int imageFadeDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsSlow)
readonly property int imageScaleDuration: MobileShell.Motion.duration(MobileShell.Motion.SpatialVerySlow)
signal requestNextPage()
function returnToLanding() {
backgroundImage.scale = scaleLanding;
contentOpacityAnim.to = 1;
contentOpacityAnim.restart();
}
property real contentOpacity: 0
MobileShell.MotionNumberAnimation on contentOpacity {
id: contentOpacityAnim
type: MobileShell.Motion.EffectsSlow
running: true
duration: root.initialContentFadeDuration
to: 1
// shorten animation after initial run
onFinished: duration = root.returnContentFadeDuration
}
Image {
id: backgroundImage
anchors.fill: parent
readonly property bool isLandscape: width >= height
source: {
const imgFile = '5120x2880.png';
const lightWallpaperFolder = 'wallpapers/SHIFT/contents/images/';
const darkWallpaperFolder = 'wallpapers/SHIFT/contents/images_dark/';
const wallpaperUrl = StandardPaths.locate(
StandardPaths.GenericDataLocation,
(Prepare.PrepareUtil.usingDarkTheme ? darkWallpaperFolder : lightWallpaperFolder) + imgFile
);
if (!wallpaperUrl) {
return StandardPaths.locate(StandardPaths.GenericDataLocation, lightWallpaperFolder + imgFile);
}
return wallpaperUrl;
}
fillMode: Image.PreserveAspectCrop
opacity: 0
MobileShell.MotionNumberAnimation on opacity {
type: MobileShell.Motion.EffectsSlow
running: true
duration: root.imageFadeDuration
to: 1
}
// zoom animation
scale: scaleStart
Component.onCompleted: scale = scaleLanding
Behavior on scale {
MobileShell.MotionNumberAnimation {
type: MobileShell.Motion.SpatialVerySlow
duration: root.imageScaleDuration
}
}
// darken image slightly
Rectangle {
anchors.fill: parent
color: Qt.rgba(0, 0, 0, 0.3)
}
}
ColumnLayout {
opacity: root.contentOpacity
spacing: Kirigami.Units.largeSpacing
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Kirigami.Units.gridUnit * 4
anchors.rightMargin: Kirigami.Units.gridUnit * 4
Label {
Layout.fillWidth: true
text: i18n("Welcome to<br/><b>SHIFT</b>")
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.Wrap
font.pointSize: 18
color: "white"
}
}
ColumnLayout {
opacity: root.contentOpacity
spacing: Kirigami.Units.largeSpacing
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
leftMargin: Kirigami.Units.gridUnit * 4
rightMargin: Kirigami.Units.gridUnit * 4
bottomMargin: Kirigami.Units.gridUnit * 2
}
Kirigami.Heading {
Layout.fillWidth: true
text: i18n("Built on<br/><b>%1</b>", InitialStartUtil.distroName)
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.Wrap
level: 5
color: "white"
}
}
Button {
id: button
anchors.bottom: parent.bottom
anchors.right: parent.right
anchors.margins: Kirigami.Units.gridUnit
topPadding: Kirigami.Units.largeSpacing
bottomPadding: Kirigami.Units.largeSpacing
leftPadding: Kirigami.Units.largeSpacing
rightPadding: Kirigami.Units.largeSpacing
opacity: root.contentOpacity
text: i18n("Next")
icon.name: "go-next-symbolic"
onClicked: {
backgroundImage.scale = scaleSteps;
contentOpacityAnim.to = 0;
contentOpacityAnim.restart();
root.requestNextPage()
}
}
}