@@ -31,7 +31,7 @@ Showable {
3131 property real showProgress: MathUtils.clamp((width + x) / width, 0, 1)
3232
3333 showAnimation: StandardAnimation { property: "x"; to: 0 }
34− hideAnimation: StandardAnimation { property: "x"; to: -width }
34+ hideAnimation: __leftHideAnimation
3535
3636 property alias dragHandleWidth: dragHandle.width
3737 property alias model: greeterContentLoader.model
@@ -40,19 +40,75 @@ Showable {
4040 readonly property bool narrowMode: !multiUser && height > width
4141 readonly property bool multiUser: LightDM.Users.count > 1
4242
43− readonly property bool leftTeaserPressed: greeterContentLoader.status == Loader.Ready &&
44− greeterContentLoader.item.leftTeaserPressed
45− readonly property bool rightTeaserPressed: greeterContentLoader.status == Loader.Ready &&
46− greeterContentLoader.item.rightTeaserPressed
47−
4843 readonly property int currentIndex: greeterContentLoader.currentIndex
4944
45+ property var __leftHideAnimation: StandardAnimation { property: "x"; to: -width }
46+ property var __rightHideAnimation: StandardAnimation { property: "x"; to: width }
47+
5048 signal selected(int uid)
5149 signal unlocked(int uid)
50+ signal tease()
51+
52+ function hideRight() {
53+ hideAnimation = __rightHideAnimation
54+ hide()
55+ }
56+
57+ Connections {
58+ target: __rightHideAnimation
59+ // Reset hide animation to default once we're finished with it
60+ onRunningChanged: if (!__rightHideAnimation.running) greeter.hideAnimation = __leftHideAnimation
61+ }
62+
63+ // Bi-directional revealer
64+ DraggingArea {
65+ id: dragHandle
66+ anchors.fill: parent
67+ enabled: greeter.narrowMode || !greeter.locked
68+ orientation: Qt.Horizontal
69+ propagateComposedEvents: true
70+
71+ Component.onCompleted: {
72+ // set evaluators to baseline of dragValue == 0
73+ leftEvaluator.reset()
74+ rightEvaluator.reset()
75+ }
76+
77+ function maybeTease() {
78+ if (!greeter.locked || greeter.narrowMode)
79+ greeter.tease();
80+ }
81+
82+ onClicked: maybeTease()
83+ onDragStart: maybeTease()
84+ onPressAndHold: {} // eat event, but no need to tease, as drag will cover it
85+
86+ onDragEnd: {
87+ if (rightEvaluator.shouldAutoComplete())
88+ greeter.hideRight()
89+ else if (leftEvaluator.shouldAutoComplete())
90+ greeter.hide();
91+ else
92+ greeter.show(); // undo drag
93+ }
5294
53− onRightTeaserPressedChanged: {
54− if (rightTeaserPressed && (!locked || narrowMode) && x == 0) {
55− teasingTimer.start();
95+ onDragValueChanged: {
96+ // dragValue is kept as a "step" value since we do this x adjusting on the fly
97+ greeter.x += dragValue
98+ }
99+
100+ EdgeDragEvaluator {
101+ id: rightEvaluator
102+ trackedPosition: dragHandle.dragValue + greeter.x
103+ maxDragDistance: parent.width
104+ direction: Direction.Rightwards
105+ }
106+
107+ EdgeDragEvaluator {
108+ id: leftEvaluator
109+ trackedPosition: dragHandle.dragValue + greeter.x
110+ maxDragDistance: parent.width
111+ direction: Direction.Leftwards
56112 }
57113 }
58114
@@ -111,45 +167,54 @@ Showable {
111167 }
112168 }
113169
114− Timer {
115− id: teasingTimer
116− interval: 200
117− }
170+ onTease: showLabelAnimation.start()
118171
119− states: [
120− State {
121− name: "teasing"
122− when: teasingTimer.running
123− PropertyChanges {
124− target: greeter
125− x: -dragHandle.hintDisplacement
172+ Label {
173+ id: swipeHint
174+ visible: greeter.shown
175+ property real baseOpacity: 0.5
176+ opacity: 0.0
177+ anchors.horizontalCenter: parent.horizontalCenter
178+ anchors.bottom: parent.bottom
179+ anchors.bottomMargin: units.gu(5)
180+ text: i18n.tr("Swipe to unlock")
181+ color: "white"
182+ font.weight: Font.Light
183+
184+ SequentialAnimation on opacity {
185+ id: showLabelAnimation
186+ running: false
187+ loops: 2
188+
189+ StandardAnimation {
190+ from: 0.0
191+ to: swipeHint.baseOpacity
192+ duration: UbuntuAnimation.SleepyDuration
126193 }
127− }
128− ]
129− transitions: [
130− Transition {
131− from: "*"
132− to: "*"
133− NumberAnimation {
134− target: greeter
135− property: "x"
136− duration: 300
137− easing.type: Easing.OutCubic
194+ PauseAnimation { duration: UbuntuAnimation.BriskDuration }
195+ StandardAnimation {
196+ from: swipeHint.baseOpacity
197+ to: 0.0
198+ duration: UbuntuAnimation.SleepyDuration
138199 }
139200 }
140− ]
141−
142− DragHandle {
143− id: dragHandle
201+ }
144202
203+ // right side shadow
204+ Image {
205+ anchors.left: parent.right
145206 anchors.top: parent.top
146207 anchors.bottom: parent.bottom
147− anchors.right: parent.right
148−
149− hintDisplacement: units.gu(2)
150−
151− enabled: greeter.narrowMode || !greeter.locked
208+ fillMode: Image.Tile
209+ source: "../graphics/dropshadow_right.png"
210+ }
152211
153− direction: Direction.Leftwards
212+ // left side shadow
213+ Image {
214+ anchors.right: parent.left
215+ anchors.top: parent.top
216+ anchors.bottom: parent.bottom
217+ fillMode: Image.Tile
218+ source: "../graphics/dropshadow_left.png"
154219 }
155220}