lockscreen: Refactor and use loaders to speed up lockscreen load time

This commit is contained in:
Devin Lin 2022-02-17 00:52:34 -05:00
parent 2fa24cd0e2
commit d26464172a
11 changed files with 276 additions and 368 deletions

View file

@ -1,7 +1,6 @@
/*
SPDX-FileCopyrightText: 2019 Nicolas Fella <nicolas.fella@gmx.de>
SPDX-License-Identifier: GPL-2.0-or-later
* SPDX-FileCopyrightText: 2019 Nicolas Fella <nicolas.fella@gmx.de>
* SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick 2.8
@ -12,10 +11,13 @@ import QtGraphicalEffects 1.12
import org.kde.plasma.core 2.0
ColumnLayout {
readonly property bool softwareRendering: GraphicsInfo.api === GraphicsInfo.Software
id: root
property int layoutAlignment
property int alignment
Layout.alignment: alignment
readonly property bool softwareRendering: GraphicsInfo.api === GraphicsInfo.Software
readonly property bool is24HourTime: Qt.locale().timeFormat(Locale.ShortFormat).toLowerCase().indexOf("ap") === -1
Layout.alignment: layoutAlignment
spacing: Units.gridUnit
Label {
@ -24,7 +26,7 @@ ColumnLayout {
style: softwareRendering ? Text.Outline : Text.Normal
styleColor: softwareRendering ? ColorScope.backgroundColor : "transparent" // no outline, doesn't matter
Layout.alignment: alignment
Layout.alignment: root.layoutAlignment
font.weight: Font.Light // this font weight may switch to regular on distros that don't have a light variant
font.pointSize: 36
layer.enabled: true
@ -35,13 +37,14 @@ ColumnLayout {
color: "#757575"
}
}
Label {
text: Qt.formatDate(timeSource.data["Local"]["DateTime"], "ddd, MMM d")
color: ColorScope.textColor
style: softwareRendering ? Text.Outline : Text.Normal
styleColor: softwareRendering ? ColorScope.backgroundColor : "transparent" // no outline, doesn't matter
Layout.alignment: alignment
Layout.alignment: root.layoutAlignment
font.pointSize: 10
layer.enabled: true
layer.effect: DropShadow {
@ -51,6 +54,7 @@ ColumnLayout {
color: "#757575"
}
}
DataSource {
id: timeSource
engine: "time"

View file

@ -31,6 +31,9 @@ Flickable {
}
function updateState() {
// don't update state if at end
if (position <= 0 || position >= keypadHeight) return;
if (movingUp) {
goToOpenPosition();
} else {
@ -72,7 +75,7 @@ Flickable {
property real oldContentY
onContentYChanged: {
positionChangedDueToFlickable = true;
position += (contentY - oldContentY);
position = Math.max(0, Math.min(keypadHeight, position + (contentY - oldContentY)));
oldContentY = contentY;
}

View file

@ -1,65 +0,0 @@
/*
This file is part of the KDE project.
SPDX-FileCopyrightText: 2014 Aleix Pol Gonzalez <aleixpol@blue-systems.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
PlasmaCore.FrameSvgItem {
id: osd
property alias timeout: osdItem.timeout
property alias osdValue: osdItem.osdValue
property alias osdMaxValue: osdItem.osdMaxValue
property alias icon: osdItem.icon
property alias showingProgress: osdItem.showingProgress
objectName: "onScreenDisplay"
visible: false
width: osdItem.width + margins.left + margins.right
height: osdItem.height + margins.top + margins.bottom
imagePath: "widgets/background"
function show() {
osd.visible = true;
hideAnimation.restart();
}
// avoid leaking ColorScope of lock screen theme into the OSD "popup"
PlasmaCore.ColorScope {
width: osdItem.width
height: osdItem.height
anchors.centerIn: parent
colorGroup: PlasmaCore.Theme.NormalColorGroup
OsdItem {
id: osdItem
}
}
SequentialAnimation {
id: hideAnimation
// prevent press and hold from flickering
PauseAnimation { duration: 100 }
NumberAnimation {
target: osd
property: "opacity"
from: 1
to: 0
duration: osd.timeout
easing.type: Easing.InQuad
}
ScriptAction {
script: {
osd.visible = false;
osd.opacity = 1;
osd.icon = "";
osd.osdValue = 0;
}
}
}
}

View file

@ -1,6 +1,6 @@
/*
* SPDX-FileCopyrightText: 2019 Nicolas Fella <nicolas.fella@gmx.de>
* SPDX-FileCopyrightText: 2021 Devin Lin <espidev@gmail.com>
* SPDX-FileCopyrightText: 2021-2022 Devin Lin <espidev@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
@ -8,12 +8,9 @@
import QtQuick 2.12
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1
import QtGraphicalEffects 1.12
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.workspace.keyboardlayout 1.0
import org.kde.notificationmanager 1.1 as Notifications
import org.kde.plasma.private.mobileshell 1.0 as MobileShell
PlasmaCore.ColorScope {
id: root
@ -22,42 +19,27 @@ PlasmaCore.ColorScope {
property bool isWidescreen: root.height < root.width * 0.75
property bool notificationsShown: false
property bool is24HourTime: Qt.locale().timeFormat(Locale.ShortFormat).toLowerCase().indexOf("ap") === -1
colorGroup: PlasmaCore.Theme.ComplementaryColorGroup
anchors.fill: parent
readonly property bool drawerOpen: flickable.openFactor >= 1
function isPinDrawerOpen() {
return flickable.openFactor >= 1;
}
function askPassword() {
flickable.goToOpenPosition();
}
colorGroup: PlasmaCore.Theme.ComplementaryColorGroup
anchors.fill: parent
Notifications.WatchedNotificationsModel {
id: notifModel
}
// blur background once keypad is open
FastBlur {
id: blur
cached: true
// wallpaper blur
Loader {
anchors.fill: parent
source: wallpaper
radius: 50
opacity: 0
property bool doBlur: notificationsShown || isPinDrawerOpen() // only blur once animation finished for performance
Behavior on doBlur {
NumberAnimation {
target: blur
property: "opacity"
duration: 1000
to: blur.doBlur ? 0 : 1
easing.type: Easing.InOutQuad
}
asynchronous: true
sourceComponent: WallpaperBlur {
source: wallpaper
blur: root.notificationsShown || root.drawerOpen // only blur once animation finished for performance
}
}
@ -67,7 +49,12 @@ PlasmaCore.ColorScope {
property real openFactor: position / keypadHeight
Component.onCompleted: flickable.goToClosePosition()
keypadHeight: PlasmaCore.Units.gridUnit * 20
Component.onCompleted: {
flickable.position = 0;
flickable.goToClosePosition();
}
onPositionChanged: {
if (position > keypadHeight) {
@ -77,171 +64,50 @@ PlasmaCore.ColorScope {
}
}
keypadHeight: PlasmaCore.Units.gridUnit * 20
Item {
width: flickable.width
height: flickable.height
y: flickable.contentY // effectively anchored to the screen
// header bar
Loader {
id: headerBar
asynchronous: true
anchors {
top: parent.top
left: parent.left
right: parent.right
}
height: PlasmaCore.Units.gridUnit * 1.25
StatusBarComponent {
id: statusBar
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
opacity: 1 - flickable.openFactor
sourceComponent: MobileShell.StatusBar {
id: statusBar
colorGroup: PlasmaCore.Theme.ComplementaryColorGroup
backgroundColor: "transparent"
showSecondRow: false
showDropShadow: true
showTime: false
disableSystemTray: true // HACK: prevent SIGABRT
}
}
// phone lockscreen component
Loader {
LockScreenNarrowContent {
id: phoneComponent
visible: !isWidescreen
active: visible
opacity: 1 - flickable.openFactor
asynchronous: true
anchors {
top: parent.top
bottom: scrollUpIcon.top
left: parent.left
right: parent.right
topMargin: item && !root.notificationsShown ? Math.round(root.height / 2 - (item.implicitHeight / 2 + PlasmaCore.Units.gridUnit * 2)) : PlasmaCore.Units.gridUnit * 5
bottomMargin: PlasmaCore.Units.gridUnit
}
fullHeight: root.height
Behavior on anchors.topMargin {
NumberAnimation {
duration: loadTimer.running ? 0 : PlasmaCore.Units.longDuration
easing.type: Easing.InOutQuad
}
}
// avoid topMargin animation when item is being loaded
onLoaded: loadTimer.restart();
Timer {
id: loadTimer
interval: PlasmaCore.Units.longDuration
}
anchors.top: parent.top
anchors.bottom: scrollUpIcon.top
anchors.left: parent.left
anchors.right: parent.right
// move while swiping up
transform: Translate { y: Math.round((1 - phoneComponent.opacity) * (-root.height / 6)) }
sourceComponent: ColumnLayout {
id: phoneClockComponent
spacing: 0
Clock {
id: phoneClock
alignment: Qt.AlignHCenter
Layout.bottomMargin: PlasmaCore.Units.gridUnit * 2 // keep spacing even if media controls are gone
}
MobileShell.MediaControlsWidget {
Layout.alignment: Qt.AlignHCenter
Layout.fillWidth: true
Layout.maximumWidth: PlasmaCore.Units.gridUnit * 25
Layout.leftMargin: PlasmaCore.Units.gridUnit
Layout.rightMargin: PlasmaCore.Units.gridUnit
}
NotificationsComponent {
Layout.fillHeight: true
Layout.fillWidth: true
Layout.maximumWidth: PlasmaCore.Units.gridUnit * (25 + 2) // clip margins
topMargin: PlasmaCore.Units.gridUnit
leftMargin: PlasmaCore.Units.gridUnit
rightMargin: PlasmaCore.Units.gridUnit
}
}
}
// tablet lockscreen component
Loader {
LockScreenWideScreenContent {
id: tabletComponent
visible: isWidescreen
active: visible
opacity: 1 - flickable.openFactor
asynchronous: true
anchors.top: headerBar.bottom
anchors.top: statusBar.bottom
anchors.bottom: scrollUpIcon.top
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: scrollUpIcon.top
// move while swiping up
transform: Translate { y: Math.round((1 - phoneComponent.opacity) * (-root.height / 6)) }
sourceComponent: Item {
Item {
id: tabletClockComponent
width: parent.width / 2
anchors {
top: parent.top
bottom: parent.bottom
left: parent.left
leftMargin: PlasmaCore.Units.gridUnit * 3
}
ColumnLayout {
id: tabletLayout
anchors.centerIn: parent
spacing: PlasmaCore.Units.gridUnit
Clock {
id: tabletClock
alignment: Qt.AlignLeft
Layout.fillWidth: true
Layout.minimumWidth: PlasmaCore.Units.gridUnit * 20
}
MobileShell.MediaControlsWidget {
Layout.alignment: Qt.AlignLeft
Layout.fillWidth: true
Layout.maximumWidth: PlasmaCore.Units.gridUnit * 25
}
}
}
// tablet notifications list
ColumnLayout {
id: tabletNotificationsList
anchors {
top: parent.top
bottom: parent.bottom
left: tabletClockComponent.right
right: parent.right
rightMargin: PlasmaCore.Units.gridUnit
}
NotificationsComponent {
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
Layout.fillWidth: true
Layout.fillHeight: true
Layout.topMargin: PlasmaCore.Units.gridUnit * 2
Layout.bottomMargin: PlasmaCore.Units.gridUnit
Layout.minimumWidth: PlasmaCore.Units.gridUnit * 15
Layout.maximumWidth: PlasmaCore.Units.gridUnit * 25
leftMargin: PlasmaCore.Units.gridUnit
rightMargin: PlasmaCore.Units.gridUnit
bottomMargin: PlasmaCore.Units.gridUnit
topMargin: PlasmaCore.Units.gridUnit
}
}
}
}
// scroll up icon
@ -279,20 +145,13 @@ PlasmaCore.ColorScope {
Keypad {
id: keypad
Layout.fillWidth: true
focus: true
swipeProgress: flickable.openFactor
Layout.fillWidth: true
onPasswordChanged: {
passwordFlickable.contentY = passwordFlickable.contentHeight - passwordFlickable.height
}
onPasswordChanged: flickable.goToOpenPosition()
}
}
}
}
LockOsd {
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: PlasmaCore.Units.largeSpacing
}
}

View file

@ -0,0 +1,76 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Devin Lin <espidev@gmail.com>
* SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick 2.12
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.workspace.keyboardlayout 1.0
import org.kde.notificationmanager 1.1 as Notifications
import org.kde.plasma.private.mobileshell 1.0 as MobileShell
Loader {
id: root
asynchronous: true
property real fullHeight
property bool notificationsShown: false
// avoid topMargin animation when item is being loaded
onLoaded: loadTimer.restart();
Timer {
id: loadTimer
interval: PlasmaCore.Units.longDuration
}
// move while swiping up
transform: Translate { y: Math.round((1 - phoneComponent.opacity) * (-root.height / 6)) }
sourceComponent: Item {
ColumnLayout {
id: column
spacing: 0
// center clock when no notifications are shown, otherwise move the clock upward
anchors.topMargin: !root.notificationsShown ? Math.round(root.fullHeight / 2 - (column.implicitHeight / 2)) : PlasmaCore.Units.gridUnit * 5
anchors.bottomMargin: PlasmaCore.Units.gridUnit
anchors.fill: parent
// animate
Behavior on anchors.topMargin {
NumberAnimation {
duration: loadTimer.running ? 0 : PlasmaCore.Units.longDuration
easing.type: Easing.InOutQuad
}
}
Clock {
layoutAlignment: Qt.AlignHCenter
Layout.bottomMargin: PlasmaCore.Units.gridUnit * 2 // keep spacing even if media controls are gone
}
MobileShell.MediaControlsWidget {
Layout.alignment: Qt.AlignHCenter
Layout.fillWidth: true
Layout.maximumWidth: PlasmaCore.Units.gridUnit * 25
Layout.leftMargin: PlasmaCore.Units.gridUnit
Layout.rightMargin: PlasmaCore.Units.gridUnit
}
NotificationsComponent {
id: notificationComponent
Layout.fillHeight: true
Layout.fillWidth: true
Layout.maximumWidth: PlasmaCore.Units.gridUnit * (25 + 2) // clip margins
topMargin: PlasmaCore.Units.gridUnit
leftMargin: PlasmaCore.Units.gridUnit
rightMargin: PlasmaCore.Units.gridUnit
onNotificationsShownChanged: root.notificationsShown = notificationsShown
}
}
}
}

View file

@ -0,0 +1,82 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Devin Lin <espidev@gmail.com>
* SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick 2.12
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.workspace.keyboardlayout 1.0
import org.kde.notificationmanager 1.1 as Notifications
import org.kde.plasma.private.mobileshell 1.0 as MobileShell
Loader {
id: tabletComponent
asynchronous: true
property bool notificationsShown: false
sourceComponent: Item {
Item {
id: tabletClockComponent
width: parent.width / 2
anchors {
top: parent.top
bottom: parent.bottom
left: parent.left
leftMargin: PlasmaCore.Units.gridUnit * 3
}
ColumnLayout {
id: tabletLayout
anchors.centerIn: parent
spacing: PlasmaCore.Units.gridUnit
Clock {
layoutAlignment: Qt.AlignLeft
Layout.fillWidth: true
Layout.minimumWidth: PlasmaCore.Units.gridUnit * 20
}
MobileShell.MediaControlsWidget {
Layout.alignment: Qt.AlignLeft
Layout.fillWidth: true
Layout.maximumWidth: PlasmaCore.Units.gridUnit * 25
}
}
}
// tablet notifications list
ColumnLayout {
id: tabletNotificationsList
anchors {
top: parent.top
bottom: parent.bottom
left: tabletClockComponent.right
right: parent.right
rightMargin: PlasmaCore.Units.gridUnit
}
NotificationsComponent {
id: notificationComponent
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
Layout.fillWidth: true
Layout.fillHeight: true
Layout.topMargin: PlasmaCore.Units.gridUnit * 2
Layout.bottomMargin: PlasmaCore.Units.gridUnit
Layout.minimumWidth: PlasmaCore.Units.gridUnit * 15
Layout.maximumWidth: PlasmaCore.Units.gridUnit * 25
leftMargin: PlasmaCore.Units.gridUnit
rightMargin: PlasmaCore.Units.gridUnit
bottomMargin: PlasmaCore.Units.gridUnit
topMargin: PlasmaCore.Units.gridUnit
onNotificationsShownChanged: root.notificationsShown = notificationsShown
}
}
}
}

View file

@ -15,14 +15,17 @@ import org.kde.plasma.private.mobileshell 1.0 as MobileShell
Rectangle {
id: rect
color: "transparent"
clip: true
readonly property bool notificationsShown: notificationsList.hasNotifications
property real leftMargin: 0
property real rightMargin: 0
property real topMargin: 0
property real bottomMargin: 0
color: "transparent"
clip: true
PlasmaCore.ColorScope {
anchors.fill: parent
anchors.topMargin: rect.topMargin
@ -34,18 +37,19 @@ Rectangle {
Connections {
target: authenticator
function onSucceeded() {
if (phoneNotificationsList.requestNotificationAction) {
phoneNotificationsList.runPendingAction();
phoneNotificationsList.requestNotificationAction = false;
// run pending action if successfully unlocked
if (notificationsList.requestNotificationAction) {
notificationsList.runPendingAction();
notificationsList.requestNotificationAction = false;
}
}
function onFailed() {
phoneNotificationsList.requestNotificationAction = false;
notificationsList.requestNotificationAction = false;
}
}
MobileShell.NotificationsWidget {
id: phoneNotificationsList
id: notificationsList
anchors.fill: parent
historyModelType: MobileShell.NotificationsModelType.WatchedNotificationsModel
@ -54,7 +58,6 @@ Rectangle {
property bool requestNotificationAction: false
onHasNotificationsChanged: root.notificationsShown = hasNotifications
onUnlockRequested: {
requestNotificationAction = true;
root.askPassword();

View file

@ -1,107 +0,0 @@
/*
* SPDX-FileCopyrightText: 2014 Martin Klapetek <mklapetek@kde.org>
* SPDX-FileCopyrightText: 2019 Kai Uwe Broulik <kde@broulik.de>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick 2.14
import QtQuick.Layouts 1.1
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents3
import org.kde.plasma.extras 2.0 as PlasmaExtra
import QtQuick.Window 2.2
RowLayout {
// OSD Timeout in msecs - how long it will stay on the screen
property int timeout: 1800
// This is either a text or a number, if showingProgress is set to true,
// the number will be used as a value for the progress bar
property var osdValue
// Maximum percent value
property int osdMaxValue: 100
// Icon name to display
property string icon
// Set to true if the value is meant for progress bar,
// false for displaying the value as normal text
property bool showingProgress: false
spacing: PlasmaCore.Units.smallSpacing
width: Math.max(Math.min(Screen.desktopAvailableWidth / 2, implicitWidth), PlasmaCore.Units.gridUnit * 15)
height: PlasmaCore.Units.iconSizes.medium
PlasmaCore.IconItem {
Layout.leftMargin: PlasmaCore.Units.smallSpacing
Layout.preferredWidth: PlasmaCore.Units.iconSizes.medium
Layout.preferredHeight: PlasmaCore.Units.iconSizes.medium
Layout.alignment: Qt.AlignVCenter
source: icon
visible: valid
}
PlasmaComponents3.ProgressBar {
id: progressBar
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
// So it never exceeds the minimum popup size
Layout.preferredWidth: 1
Layout.rightMargin: PlasmaCore.Units.smallSpacing
visible: showingProgress
from: 0
to: osdMaxValue
value: Number(osdValue)
}
// Get the width of a three-digit number so we can size the label
// to the maximum width to avoid the progress bad resizing itself
TextMetrics {
id: widestLabelSize
text: i18n("100%")
font: percentageLabel.font
}
// Numerical display of progress bar value
PlasmaExtra.Heading {
id: percentageLabel
Layout.fillHeight: true
Layout.preferredWidth: widestLabelSize.width
Layout.rightMargin: PlasmaCore.Units.smallSpacing
Layout.alignment: Qt.AlignVCenter
level: 3
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: i18nc("Percentage value", "%1%", progressBar.value)
visible: showingProgress
// Display a subtle visual indication that the volume might be
// dangerously high
// ------------------------------------------------
// Keep this in sync with the copies in plasma-pa:ListItemBase.qml
// and plasma-pa:VolumeSlider.qml
color: {
if (progressBar.value <= 100) {
return PlasmaCore.Theme.textColor
} else if (progressBar.value > 100 && progressBar.value <= 125) {
return PlasmaCore.Theme.neutralTextColor
} else {
return PlasmaCore.Theme.negativeTextColor
}
}
}
PlasmaExtra.Heading {
id: label
Layout.fillWidth: true
Layout.fillHeight: true
Layout.rightMargin: PlasmaCore.Units.smallSpacing
Layout.alignment: Qt.AlignVCenter
level: 3
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
textFormat: Text.PlainText
wrapMode: Text.NoWrap
elide: Text.ElideRight
text: !showingProgress && osdValue ? osdValue : ""
visible: !showingProgress
}
}

View file

@ -1,8 +1,7 @@
/*
SPDX-FileCopyrightText: 2020-2021 Devin Lin <espidev@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
* SPDX-FileCopyrightText: 2020-2021 Devin Lin <espidev@gmail.com>
* SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick 2.12
import QtQuick.Controls 2.1

View file

@ -0,0 +1,28 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Devin Lin <espidev@gmail.com>
* SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick 2.12
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.private.mobileshell 1.0 as MobileShell
Loader {
active: true
asynchronous: true
height: PlasmaCore.Units.gridUnit * 1.25
sourceComponent: MobileShell.StatusBar {
id: statusBar
colorGroup: PlasmaCore.Theme.ComplementaryColorGroup
backgroundColor: "transparent"
showSecondRow: false
showDropShadow: true
showTime: false
disableSystemTray: true // HACK: prevent SIGABRT
}
}

View file

@ -0,0 +1,26 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Devin Lin <devin@kde.org>
* SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick 2.12
import QtGraphicalEffects 1.12
FastBlur {
id: fastBlur
cached: true
radius: 50
opacity: 0
property bool blur
Behavior on blur {
NumberAnimation {
target: fastBlur
property: "opacity"
duration: 1000
to: fastBlur.blur ? 0 : 1
easing.type: Easing.InOutQuad
}
}
}