LockScreen.qml 8.39 KB
Newer Older
Nicolas Fella's avatar
Nicolas Fella committed
1 2
/*
Copyright (C) 2019 Nicolas Fella <nicolas.fella@gmx.de>
3

Marco Martin's avatar
Marco Martin committed
4 5 6 7
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Aaron J. Seigo's avatar
Aaron J. Seigo committed
8

Marco Martin's avatar
Marco Martin committed
9 10
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
Nicolas Fella's avatar
Nicolas Fella committed
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Marco Martin's avatar
Marco Martin committed
12
GNU General Public License for more details.
Aaron J. Seigo's avatar
Aaron J. Seigo committed
13

Marco Martin's avatar
Marco Martin committed
14 15
You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
Nicolas Fella's avatar
Nicolas Fella committed
16
*/
Aaron J. Seigo's avatar
time  
Aaron J. Seigo committed
17

Nicolas Fella's avatar
Nicolas Fella committed
18
import QtQuick 2.12
Marco Martin's avatar
Marco Martin committed
19
import QtQuick.Controls 1.1
Nicolas Fella's avatar
Nicolas Fella committed
20
import QtQuick.Layouts 1.1
Nicolas Fella's avatar
Nicolas Fella committed
21
import QtGraphicalEffects 1.12
Nicolas Fella's avatar
Nicolas Fella committed
22
import org.kde.plasma.components 2.0 as PlasmaComponents
Marco Martin's avatar
Marco Martin committed
23
import org.kde.plasma.core 2.0 as PlasmaCore
Nicolas Fella's avatar
Nicolas Fella committed
24
import org.kde.plasma.workspace.keyboardlayout 1.0
Devin Lin's avatar
Devin Lin committed
25
import org.kde.notificationmanager 1.1 as Notifications
Marco Martin's avatar
Marco Martin committed
26
import "../components"
Aaron J. Seigo's avatar
time  
Aaron J. Seigo committed
27

Nicolas Fella's avatar
Nicolas Fella committed
28
PlasmaCore.ColorScope {
Nicolas Fella's avatar
Nicolas Fella committed
29 30 31
    id: root

    property string password
Devin Lin's avatar
Devin Lin committed
32 33 34
    
    property bool isWidescreen: root.height < root.width * 0.75
    property bool notificationsShown: phoneNotificationsList.count !== 0
Nicolas Fella's avatar
Nicolas Fella committed
35

36 37
    property bool is24HourTime: Qt.locale().timeFormat(Locale.ShortFormat).toLowerCase().indexOf("ap") === -1
    
Nicolas Fella's avatar
Nicolas Fella committed
38 39
    colorGroup: PlasmaCore.Theme.ComplementaryColorGroup
    anchors.fill: parent
40
    
Devin Lin's avatar
Devin Lin committed
41 42 43
    function isPinDrawerOpen() {
        return passwordFlickable.contentY === passwordFlickable.columnHeight;
    }
44 45 46 47 48 49 50 51 52 53 54 55 56

    function askPassword() {
        showPasswordAnim.restart();
    }
    NumberAnimation {
        id: showPasswordAnim
        target: passwordFlickable
        property: "contentY"
        from: 0
        to: passwordFlickable.contentHeight - passwordFlickable.height
        duration: units.longDuration
        easing.type: Easing.InOutQuad
    }
Devin Lin's avatar
Devin Lin committed
57 58 59 60
    // blur background once keypad is open
    FastBlur {
        id: blur
        cached: true
Nicolas Fella's avatar
Nicolas Fella committed
61 62
        anchors.fill: parent
        source: wallpaper
63 64
        radius: 50
        opacity: 0
65
        
Devin Lin's avatar
Devin Lin committed
66 67 68 69 70
        property bool doBlur: notificationsShown || isPinDrawerOpen() // only blur once animation finished for performance
        
        Behavior on doBlur {
            NumberAnimation {
                target: blur
71
                property: "opacity"
Devin Lin's avatar
Devin Lin committed
72
                duration: 1000
73
                to: blur.doBlur ? 0 : 1
Devin Lin's avatar
Devin Lin committed
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
                easing.type: Easing.InOutQuad
            }
        }
    }
    
    Notifications.WatchedNotificationsModel {
        id: notifModel
    }
    
    // header bar
    SimpleHeaderBar {
        anchors {
            top: parent.top
            left: parent.left
            right: parent.right
        }
        height: units.gridUnit
91
        opacity: 1 - (passwordFlickable.contentY / passwordFlickable.columnHeight)
Nicolas Fella's avatar
Nicolas Fella committed
92
    }
Devin Lin's avatar
Devin Lin committed
93 94 95 96 97 98 99 100 101 102 103 104 105
    
    // phone clock component
    ColumnLayout {
        id: phoneClockComponent
        visible: !isWidescreen
        
        anchors {
            top: parent.top
            topMargin: root.height / 2 - (height / 2 + units.gridUnit * 2)
            left: parent.left
            right: parent.right
        }
        spacing: 0
106
        opacity: 1 - (passwordFlickable.contentY / passwordFlickable.columnHeight)
Devin Lin's avatar
Devin Lin committed
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
        
        states: State {
            name: "notification"; when: notificationsShown
            PropertyChanges { target: phoneClockComponent; anchors.topMargin: units.gridUnit * 5 }
        }
        
        transitions: Transition {
            NumberAnimation {
                properties: "anchors.topMargin"
                easing.type: Easing.InOutQuad
            }
        }
        
        Clock {
            id: phoneClock
            alignment: Qt.AlignHCenter
            Layout.bottomMargin: units.gridUnit * 2 // keep spacing even if media controls are gone
        }
        MediaControls {
            Layout.alignment: Qt.AlignHCenter
            Layout.fillWidth: true
            Layout.maximumWidth: units.gridUnit * 25
            Layout.minimumWidth: units.gridUnit * 15
            Layout.leftMargin: units.gridUnit
            Layout.rightMargin: units.gridUnit
            z: 5
        }
134 135
    }
    
Devin Lin's avatar
Devin Lin committed
136 137 138 139 140
    // tablet clock component
    Item {
        id: tabletClockComponent
        visible: isWidescreen
        width: parent.width / 2   
141
        anchors {
Devin Lin's avatar
Devin Lin committed
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
            top: parent.top
            bottom: parent.bottom
            left: parent.left
            leftMargin: units.gridUnit * 3
        }
        
        ColumnLayout {
            id: tabletLayout
            anchors.centerIn: parent
            spacing: units.gridUnit
            opacity: 1 - (passwordFlickable.contentY / passwordFlickable.columnHeight)
            
            Clock {
                id: tabletClock
                alignment: Qt.AlignLeft
                Layout.fillWidth: true
                Layout.minimumWidth: units.gridUnit * 20
            }
            MediaControls {
                Layout.alignment: Qt.AlignLeft
                Layout.fillWidth: true
                Layout.maximumWidth: units.gridUnit * 25
                Layout.minimumWidth: units.gridUnit * 20
                z: 5
            }
        }
    }
    
    // phone notifications list
    NotificationsList {
        id: phoneNotificationsList
        visible: !isWidescreen
        z: passwordFlickable.contentY === 0 ? 5 : 0 // prevent mousearea from interfering with pin drawer
        anchors {
            top: phoneClockComponent.bottom
            topMargin: units.gridUnit
            bottom: scrollUpIcon.top
            bottomMargin: units.gridUnit
180 181 182 183
            left: parent.left
            right: parent.right
        }
    }
Devin Lin's avatar
Devin Lin committed
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
    
    // tablet notifications list
    ColumnLayout {
        visible: isWidescreen
        z: passwordFlickable.contentY === 0 ? 5 : 0 // prevent mousearea from interfering with pin drawer
        anchors {
            top: parent.top
            bottom: parent.bottom
            left: tabletClockComponent.right
            right: parent.right
            rightMargin: units.gridUnit
        }
        
        NotificationsList {
            Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
            Layout.fillWidth: true
            Layout.minimumHeight: this.notificationListHeight
            Layout.minimumWidth: units.gridUnit * 15
            Layout.maximumWidth: units.gridUnit * 25
        }
    }
    
    // scroll up icon
207
    PlasmaCore.IconItem {
Devin Lin's avatar
Devin Lin committed
208
        id: scrollUpIcon
209
        anchors.bottom: parent.bottom
210
        anchors.bottomMargin: units.gridUnit + passwordFlickable.contentY * 0.5
211 212 213
        anchors.horizontalCenter: parent.horizontalCenter
        opacity: 1 - (passwordFlickable.contentY / passwordFlickable.columnHeight)
        
214 215
        colorGroup: PlasmaCore.Theme.ComplementaryColorGroup
        source: "arrow-up"
Aaron J. Seigo's avatar
time  
Aaron J. Seigo committed
216 217
    }

218 219 220 221 222 223 224 225 226 227 228 229
    Flickable {
        id: passwordFlickable
        
        anchors.fill: parent
        
        property int columnHeight: units.gridUnit * 20
        
        height: columnHeight + root.height
        contentHeight: columnHeight + root.height
        boundsBehavior: Flickable.StopAtBounds
        
        // always snap to end (either hidden or shown)
230
        onMovementEnded: {
231 232 233 234 235 236 237
            if (!atYBeginning && !atYEnd) {
                if (contentY > columnHeight - contentY) {
                    flick(0, -1000);
                } else {
                    flick(0, 1000);
                }
            }
238 239 240 241
        }

        // wipe password if it is more than half way down the screen
        onContentYChanged: {
Devin Lin's avatar
Devin Lin committed
242
            if (contentY < columnHeight / 2) {
243
                keypad.reset();
Devin Lin's avatar
Devin Lin committed
244
            }
Nicolas Fella's avatar
Nicolas Fella committed
245
        }
246 247 248 249 250 251
        
        ColumnLayout {
            id: passwordLayout
            anchors.bottom: parent.bottom
            
            width: parent.width
Devin Lin's avatar
Devin Lin committed
252
            spacing: units.gridUnit
253 254
            opacity: Math.sin((Math.PI / 2) * (passwordFlickable.contentY / passwordFlickable.columnHeight) + 1.5 * Math.PI) + 1
            
Devin Lin's avatar
Devin Lin committed
255 256
            // scroll down icon
            PlasmaCore.IconItem {
257
                Layout.alignment: Qt.AlignHCenter
Devin Lin's avatar
Devin Lin committed
258 259
                colorGroup: PlasmaCore.Theme.ComplementaryColorGroup
                source: "arrow-down"
260
            }
Aaron J. Seigo's avatar
Aaron J. Seigo committed
261

Devin Lin's avatar
Devin Lin committed
262 263 264
            Keypad {
                id: keypad
                focus: passwordFlickable.contentY === passwordFlickable.columnHeight
Nicolas Fella's avatar
Nicolas Fella committed
265
                Layout.fillWidth: true
Devin Lin's avatar
Devin Lin committed
266
                Layout.minimumHeight: units.gridUnit * 17
267
                Layout.maximumWidth: root.width
Nicolas Fella's avatar
Nicolas Fella committed
268
            }
Aaron J. Seigo's avatar
Aaron J. Seigo committed
269 270 271
        }
    }
}