@@ -15,7 +15,9 @@
1515 */
1616
1717import QtQuick 2.4
18+import QtQuick.Window 2.2
1819import Ubuntu.Components 1.3
20+import Ubuntu.Telephony 0.1 as Telephony
1921import "../Components"
2022
2123FocusScope {
@@ -23,34 +25,40 @@ FocusScope {
2325
2426 property alias dragHandleLeftMargin: coverPage.dragHandleLeftMargin
2527 property alias launcherOffset: coverPage.launcherOffset
26− property int currentIndex // unused
27− property alias delayMinutes: lockscreen.delayMinutes
28+ property alias currentIndex: loginList.currentIndex
29+ property alias delayMinutes: delayedLockscreen.delayMinutes
2830 property alias backgroundTopMargin: coverPage.backgroundTopMargin
2931 property url background
32+ property bool hasCustomBackground
3033 property bool locked
31− property bool alphanumeric
32− property var userModel // unused
34+ property alias alphanumeric: loginList.alphanumeric
35+ property alias userModel: loginList.model
3336 property alias infographicModel: coverPage.infographicModel
37+ property string sessionToStart
3438 property bool waiting
3539 readonly property bool fullyShown: coverPage.showProgress === 1 || lockscreen.shown
3640 readonly property bool required: coverPage.required || lockscreen.required
3741 readonly property bool animating: coverPage.showAnimation.running || coverPage.hideAnimation.running
3842
39− signal selected(int index) // unused
43+ // so that it can be replaced in tests with a mock object
44+ property var inputMethod: Qt.inputMethod
45+
46+ signal selected(int index)
4047 signal responded(string response)
4148 signal tease()
4249 signal emergencyCall()
4350
4451 function showMessage(html) {
45− // TODO
52+ loginList.showMessage(html);
4653 }
4754
4855 function showPrompt(text, isSecret, isDefaultPrompt) {
49− lockscreen.promptText = isDefaultPrompt ? "" : text.toLowerCase();
50− lockscreen.maybeShow();
56+ loginList.showPrompt(text, isSecret, isDefaultPrompt);
5157 }
5258
5359 function showLastChance() {
60+ /* TODO: when we finish support for resetting device after too many
61+ failed logins, we should re-add this popup.
5462 var title = lockscreen.alphaNumeric ?
5563 i18n.tr("Sorry, incorrect passphrase.") :
5664 i18n.tr("Sorry, incorrect passcode.");
@@ -59,6 +67,7 @@ FocusScope {
5967 i18n.tr("If passphrase is entered incorrectly, your phone will conduct a factory reset and all personal data will be deleted.") :
6068 i18n.tr("If passcode is entered incorrectly, your phone will conduct a factory reset and all personal data will be deleted."));
6169 lockscreen.showInfoPopup(title, text);
70+ */
6271 }
6372
6473 function hide() {
@@ -67,27 +76,24 @@ FocusScope {
6776 }
6877
6978 function notifyAuthenticationSucceeded(showFakePassword) {
70− // When using an alternate log in mechanism like fingerprints, the
71− // design is it looks like the user entered a passcode.
72− if (!alphanumeric && showFakePassword) {
73− lockscreen.showText("...."); // actual text doesn't matter, we show bullets
79+ if (showFakePassword) {
80+ loginList.showFakePassword();
7481 }
7582 }
7683
7784 function notifyAuthenticationFailed() {
78− lockscreen.customError = "";
79− lockscreen.clear(true);
85+ loginList.showError();
8086 }
8187
8288 function showErrorMessage(msg) {
8389 coverPage.showErrorMessage(msg);
84− lockscreen.customError = msg ? msg : " "; // avoid default message
85− lockscreen.clear(true);
8690 }
8791
88− function reset() {
89− lockscreen.customError = "";
90− coverPage.show();
92+ function reset(forceShow) {
93+ loginList.reset();
94+ if (forceShow) {
95+ coverPage.show();
96+ }
9197 }
9298
9399 function tryToUnlock(toTheRight) {
@@ -109,48 +115,59 @@ FocusScope {
109115 }
110116 }
111117
112− Lockscreen {
118+ Showable {
113119 id: lockscreen
114120 objectName: "lockscreen"
115−
121+ anchors.fill: parent
116122 shown: false
123+
117124 showAnimation: StandardAnimation { property: "opacity"; to: 1 }
118125 hideAnimation: StandardAnimation { property: "opacity"; to: 0 }
119− anchors.fill: parent
120− visible: required
121− enabled: !coverPage.shown
122− background: root.background
123− darkenBackground: 0.4
124− alphaNumeric: root.alphanumeric
125− minPinLength: 4
126− maxPinLength: 4
127−
128− property string promptText
129− infoText: promptText !== "" ? i18n.tr("Enter %1").arg(promptText) :
130− alphaNumeric ? i18n.tr("Enter passphrase") :
131− i18n.tr("Enter passcode")
132−
133− property string customError
134− errorText: customError !== "" ? customError :
135− promptText !== "" ? i18n.tr("Sorry, incorrect %1").arg(promptText) :
136− alphaNumeric ? i18n.tr("Sorry, incorrect passphrase") + "\n" +
137− i18n.ctr("passphrase", "Please re-enter") :
138− i18n.tr("Sorry, incorrect passcode")
139−
140− onEntered: root.responded(passphrase)
141− onCancel: coverPage.show()
142− onEmergencyCall: root.emergencyCall()
143−
144− onEnabledChanged: {
145− if (enabled) {
146− lockscreen.forceActiveFocus();
126+
127+ Wallpaper {
128+ id: lockscreenBackground
129+ objectName: "lockscreenBackground"
130+ anchors {
131+ fill: parent
132+ topMargin: root.backgroundTopMargin
147133 }
134+ source: root.background
148135 }
149136
150− onVisibleChanged: {
151− if (visible) {
152− lockscreen.forceActiveFocus();
137+ // Darken background to match CoverPage
138+ Rectangle {
139+ objectName: "lockscreenShade"
140+ anchors.fill: parent
141+ color: "black"
142+ opacity: root.hasCustomBackground ? 0.4 : 0
143+ }
144+
145+ LoginList {
146+ id: loginList
147+ objectName: "loginList"
148+
149+ anchors {
150+ horizontalCenter: parent.horizontalCenter
151+ top: parent.top
152+ bottom: parent.bottom
153153 }
154+ width: units.gu(40)
155+ boxVerticalOffset: units.gu(14)
156+ enabled: !coverPage.shown && visible
157+ visible: !delayedLockscreen.visible
158+
159+ locked: root.locked
160+
161+ onSelected: if (enabled) root.selected(index)
162+ onResponded: root.responded(response)
163+ }
164+
165+ DelayedLockscreen {
166+ id: delayedLockscreen
167+ objectName: "delayedLockscreen"
168+ anchors.fill: parent
169+ visible: delayMinutes > 0
170+ alphaNumeric: loginList.alphanumeric
154171 }
155172
156173 function maybeShow() {
@@ -172,21 +189,16 @@ FocusScope {
172189 height: parent.height
173190 width: parent.width
174191 background: root.background
192+ hasCustomBackground: root.hasCustomBackground
175193 draggable: !root.waiting
176194 onTease: root.tease()
177195 onClicked: hide()
178196
179197 onShowProgressChanged: {
180198 if (showProgress === 1) {
181− lockscreen.reset();
182− }
183−
184− if (showProgress === 0) {
185− if (root.locked) {
186− lockscreen.clear(false); // to reset focus if necessary
187− } else {
188− root.responded("");
189− }
199+ loginList.reset();
200+ } else if (showProgress === 0) {
201+ loginList.tryToUnlock();
190202 }
191203 }
192204
@@ -198,4 +210,78 @@ FocusScope {
198210 }
199211 }
200212 }
213+
214+ StyledItem {
215+ id: bottomBar
216+ visible: lockscreen.shown
217+ height: units.gu(4)
218+
219+ anchors.left: parent.left
220+ anchors.right: parent.right
221+ anchors.top: parent.bottom
222+ anchors.topMargin: - height * (1 - coverPage.showProgress)
223+ - (inputMethod && inputMethod.visible ?
224+ inputMethod.keyboardRectangle.height : 0)
225+
226+ Rectangle {
227+ color: UbuntuColors.porcelain // matches OSK background
228+ anchors.fill: parent
229+ }
230+
231+ Label {
232+ text: i18n.tr("Cancel")
233+ anchors.left: parent.left
234+ anchors.leftMargin: units.gu(2)
235+ anchors.top: parent.top
236+ anchors.bottom: parent.bottom
237+ verticalAlignment: Text.AlignVCenter
238+ font.weight: Font.Light
239+ fontSize: "small"
240+ color: UbuntuColors.slate
241+
242+ AbstractButton {
243+ anchors.fill: parent
244+ anchors.leftMargin: -units.gu(2)
245+ anchors.rightMargin: -units.gu(2)
246+ onClicked: coverPage.show()
247+ }
248+ }
249+
250+ Label {
251+ objectName: "emergencyCallLabel"
252+ text: callManager.hasCalls ? i18n.tr("Return to Call") : i18n.tr("Emergency")
253+ anchors.right: parent.right
254+ anchors.rightMargin: units.gu(2)
255+ anchors.top: parent.top
256+ anchors.bottom: parent.bottom
257+ verticalAlignment: Text.AlignVCenter
258+ font.weight: Font.Light
259+ fontSize: "small"
260+ color: UbuntuColors.slate
261+ // TODO: uncomment once bug 1616538 is fixed
262+ // visible: telepathyHelper.ready && telepathyHelper.emergencyCallsAvailable
263+ enabled: visible
264+
265+ AbstractButton {
266+ anchors.fill: parent
267+ anchors.leftMargin: -units.gu(2)
268+ anchors.rightMargin: -units.gu(2)
269+ onClicked: root.emergencyCall()
270+ }
271+ }
272+ }
273+
274+ // FIXME: It's difficult to keep something tied closely to the OSK (bug
275+ // 1616163). But as a hack to avoid the background peeking out,
276+ // we add an extra Rectangle that just serves to hide the background
277+ // during OSK animations.
278+ Rectangle {
279+ visible: bottomBar.visible
280+ height: inputMethod && inputMethod.visible ?
281+ inputMethod.keyboardRectangle.height : 0
282+ anchors.bottom: parent.bottom
283+ anchors.left: parent.left
284+ anchors.right: parent.right
285+ color: UbuntuColors.porcelain
286+ }
201287}