Merge lp:~mterry/unity8/tutorial-fixups into lp:unity8

Proposed by Michael Terry on 2016-04-28
Status: Merged
Approved by: Daniel d'Andrada on 2016-05-20
Approved revision: 2365
Merged at revision: 2445
Proposed branch: lp:~mterry/unity8/tutorial-fixups
Merge into: lp:unity8
Diff against target: 1339 lines (+289/-512)
14 files modified
qml/Components/Dialogs.qml (+3/-1)
qml/Notifications/Notifications.qml (+1/-0)
qml/Shell.qml (+12/-8)
qml/Tutorial/InactivityTimer.qml (+32/-16)
qml/Tutorial/Tutorial.qml (+7/-6)
qml/Tutorial/TutorialBottom.qml (+0/-124)
qml/Tutorial/TutorialContent.qml (+58/-141)
qml/Tutorial/TutorialLeft.qml (+2/-2)
qml/Tutorial/TutorialLeftLong.qml (+3/-1)
qml/Tutorial/TutorialPage.qml (+2/-2)
qml/Tutorial/TutorialRight.qml (+2/-2)
qml/Tutorial/TutorialTop.qml (+2/-3)
tests/qmltests/Tutorial/tst_Tutorial.qml (+165/-196)
tests/qmltests/tst_Shell.qml (+0/-10)
To merge this branch: bzr merge lp:~mterry/unity8/tutorial-fixups
Reviewer Review Type Date Requested Status
Unity8 CI Bot continuous-integration Approve on 2016-06-05
Daniel d'Andrada (community) 2016-04-28 Approve on 2016-05-20
Review via email: mp+293262@code.launchpad.net

Commit Message

Drop bottom edge tutorials completely and small fixes for other edges.

A bundle of fixes requested by Design, after living with the new tutorial for a while:

- Drop bottom edges completely. The existing in-app hints are enough, and we want to grow them rather than do it from shell. Plus they make the user interaction logic too complicated.

- Don't show any tutorials if a notification, dialog, or spread is already open.

- Left swipe:
  * Delay for 20s (instead of immediately being shown)
  * Specify "short" in text

- Top swipe:
  * Delay for 60s (instead of 30s)
  * Use "access to notifications and quick settings" (instead of "open notification bar")

- Long left swipe:
  * Delay for 10s (instead of 5s) -- need to confirm with Design
  * Move to after top swipe tutorial
  * Only show if a non-dash app is focused
  * Disable long left swipe in shell until this tutorial is shown

- Right swipe:
  * Delay for 10s (instead of 3s)
  * Require 3 apps to be open (instead of 2)
  * Remove "short or long" from text

Description of the Change

* Are there any related MPs required for this MP to build/function as expected? Please list.
 no

 * Did you perform an exploratory manual test run of your code change and any related functionality?
 Yes

 * If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
 NA

 * If you changed the UI, has there been a design review?
 Yup, Paty is good with this (r2367)

To post a comment you must log in.
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2360
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1154/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/1547
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/1507
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/1507
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1507/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1507
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1507/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1507
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1507/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1507
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1507/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1507
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1507/artifact/output/*zip*/output.zip
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1507/console

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1154/rebuild

review: Needs Fixing (continuous-integration)
Daniel d'Andrada (dandrader) wrote :

In qml/Tutorial/Tutorial.qml

"""
    property bool paused // hide any existing tutorial and don't show new ones
    property bool delayed // don't show new tutorials
"""

Looks like those two overlap or conflict a bit. Do all combinations make sense (paused && !delayed, paused && delayed, etc)?

Would it make more sense to combine those two (or more, like maybe even active) into a state or enumeration-like property?

- running (current active==true)
- paused (current active & paused)
- delayed (current active & delayed)
- off (current !active)

Also how does paused relate with the property below?

"""
    readonly property bool running: loader.item ? loader.item.running : false
"""

Can it can be paused and running at the same time?

review: Needs Information
Daniel d'Andrada (dandrader) wrote :

Getting 8 failures and lots of binding loop warnings in tst_Tutorial.

http://pastebin.ubuntu.com/16508103/

review: Needs Fixing
Daniel d'Andrada (dandrader) wrote :

Did some basic testing on my mako. Works fine.

Daniel d'Andrada (dandrader) wrote :

Please update copyright headers (years) of:
qml/Components/Dialogs.qml
qml/Tutorial/InactivityTimer.qml
qml/Tutorial/Tutorial.qml
qml/Tutorial/TutorialContent.qml
qml/Tutorial/TutorialLeft.qml
qml/Tutorial/TutorialPage.qml
qml/Tutorial/TutorialRight.qml
qml/Tutorial/TutorialTop.qml
tests/qmltests/Tutorial/tst_Tutorial.qml

lp:~mterry/unity8/tutorial-fixups updated on 2016-05-19
2361. By Michael Terry on 2016-05-19

Merge from trunk

2362. By Michael Terry on 2016-05-19

Bump copyright years

2363. By Michael Terry on 2016-05-19

Fix tutorial tests

Michael Terry (mterry) wrote :

Yes, there's a good deal of overlap between paused and delayed. Basically paused is "super-delayed". It both delays and immediately stops any currently running tutorial. So just a more urgent delayed.

All combinations are fine and logical. But I agree that an enum would make more sense maybe. Unfortunately, qml best handles enums only if they're defined in C++ first. Otherwise, what? Strings? Kind of annoying.

I could also see changing it to a function call like stopAnyCurrentTutorial() and then setting delayed. But that's less stateful/declarative.

==

As for "running" -- that indicates if any tutorial is currently being shown (vs the tutorial in general being active, but just between tutorial pages).

==

I fixed the tests and the copyrights.

Thanks!

Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2363
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1257/
Executed test runs:
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=vivid+overlay,testname=qmluitests.sh/795
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/795
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/1699
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/1649
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/1649
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1642
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1642/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1642
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1642/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1642
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1642/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1642
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1642/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1642
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1642/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1642
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1642/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1257/rebuild

review: Needs Fixing (continuous-integration)
lp:~mterry/unity8/tutorial-fixups updated on 2016-05-20
2364. By Michael Terry on 2016-05-20

Fix shell test; don't disable tutorial if we receive a call during the wizard

2365. By Michael Terry on 2016-05-20

Make a test more robust

Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2365
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1265/
Executed test runs:
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=vivid+overlay,testname=qmluitests.sh/800
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/800
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/1707
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/1657
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/1657
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1650
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1650/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1650
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1650/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1650
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1650/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1650
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1650/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1650
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1650/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1650
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1650/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1265/rebuild

review: Needs Fixing (continuous-integration)
Daniel d'Andrada (dandrader) wrote :

* Did you perform an exploratory manual test run of the code change and any related functionality?
Yes

* Did CI run pass? If not, please explain why.
No. Some unrelated failures.

review: Approve
lp:~mterry/unity8/tutorial-fixups updated on 2016-06-02
2366. By Michael Terry on 2016-06-01

Merge from trunk

2367. By Michael Terry on 2016-06-02

And also don't start tutorial timers until the wizard is done

Michael Terry (mterry) wrote :

I've merged from trunk and made one tiny change -- we don't start tutorial timers until the wizard has finished. This means that the left edge tutorial waits the proper 20s after the wizard is done. I tested too often without bothering to re-enable the wizard. :P

Paty looked at this and said it's good. So all approved.

Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2366
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1334/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/1772
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=vivid+overlay,testname=qmluitests.sh/870
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/870
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=yakkety,testname=qmluitests.sh/870
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/1798
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/1745
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/1745
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/1745
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1738
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1738/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1738
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1738/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/1738
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/1738/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1738
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1738/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1738
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1738/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/1738
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/1738/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1738
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1738/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1738
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1738/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/1738
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/1738/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1334/rebuild

review: Needs Fixing (continuous-integration)
Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:2366
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1383/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/1849
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=vivid+overlay,testname=qmluitests.sh/932
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/932
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=yakkety,testname=qmluitests.sh/932
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/1875
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/1813
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/1813
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/1813
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1804
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1804/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1804
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1804/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/1804
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/1804/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1804
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1804/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1804
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1804/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/1804
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/1804/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1804
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1804/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1804
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1804/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/1804
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/1804/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1383/rebuild

review: Approve (continuous-integration)
lp:~mterry/unity8/tutorial-fixups updated on 2016-06-10
2368. By Michael Terry on 2016-06-10

Merge from trunk

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'qml/Components/Dialogs.qml'
2--- qml/Components/Dialogs.qml 2016-05-17 20:46:51 +0000
3+++ qml/Components/Dialogs.qml 2016-06-10 14:15:49 +0000
4@@ -1,5 +1,5 @@
5 /*
6- * Copyright (C) 2014-2015 Canonical, Ltd.
7+ * Copyright (C) 2014-2016 Canonical, Ltd.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11@@ -27,6 +27,8 @@
12 Item {
13 id: root
14
15+ readonly property alias hasActiveDialog: dialogLoader.active
16+
17 // to be set from outside, useful mostly for testing purposes
18 property var unitySessionService: DBusUnitySessionService
19 property var closeAllApps: function() {
20
21=== modified file 'qml/Notifications/Notifications.qml'
22--- qml/Notifications/Notifications.qml 2016-05-18 18:14:19 +0000
23+++ qml/Notifications/Notifications.qml 2016-06-10 14:15:49 +0000
24@@ -26,6 +26,7 @@
25 objectName: "notificationList"
26 interactive: false
27
28+ readonly property bool hasNotification: count > 1 // placeholder is index 0
29 property real margin
30 property bool hasMouse
31 property url background: ""
32
33=== modified file 'qml/Shell.qml'
34--- qml/Shell.qml 2016-05-27 13:54:26 +0000
35+++ qml/Shell.qml 2016-06-10 14:15:49 +0000
36@@ -116,10 +116,9 @@
37 }
38 function _onMainAppChanged(appId) {
39 if (wizard.active && appId != "" && appId != "unity8-dash") {
40- // If this happens on first boot, we may be in edge
41- // tutorial or wizard while receiving a call. But a call
42- // is more important than wizard so just bail out of those.
43- tutorial.finish();
44+ // If this happens on first boot, we may be in the
45+ // wizard while receiving a call. But a call is more
46+ // important than the wizard so just bail out of it.
47 wizard.hide();
48 }
49
50@@ -320,7 +319,7 @@
51 Binding {
52 target: applicationsDisplayLoader.item
53 property: "inverseProgress"
54- value: greeter && greeter.locked ? 0 : launcher.progress
55+ value: !greeter || greeter.locked || !tutorial.launcherLongSwipeEnabled ? 0 : launcher.progress
56 }
57 Binding {
58 target: applicationsDisplayLoader.item
59@@ -504,7 +503,8 @@
60 launcher.fadeOut();
61 }
62
63- if (!greeter.locked && ApplicationManager.focusedApplicationId != "unity8-dash") {
64+ if (!greeter.locked && tutorial.launcherLongSwipeEnabled
65+ && ApplicationManager.focusedApplicationId != "unity8-dash") {
66 ApplicationManager.requestFocusApplication("unity8-dash")
67 launcher.fadeOut();
68 }
69@@ -623,8 +623,12 @@
70 objectName: "tutorial"
71 anchors.fill: parent
72
73- paused: callManager.hasCalls || greeter.shown
74- keyboardVisible: inputMethod.state === "shown"
75+ paused: callManager.hasCalls || !greeter || greeter.shown ||
76+ wizard.active
77+ delayed: dialogs.hasActiveDialog || notifications.hasNotification ||
78+ inputMethod.state === "shown" ||
79+ (launcher.shown && !launcher.lockedVisible) ||
80+ panel.indicators.shown || stage.dragProgress > 0
81 usageScenario: shell.usageScenario
82 lastInputTimestamp: inputFilter.lastInputTimestamp
83 launcher: launcher
84
85=== modified file 'qml/Tutorial/InactivityTimer.qml'
86--- qml/Tutorial/InactivityTimer.qml 2015-11-18 17:08:57 +0000
87+++ qml/Tutorial/InactivityTimer.qml 2016-06-10 14:15:49 +0000
88@@ -1,5 +1,5 @@
89 /*
90- * Copyright (C) 2015 Canonical, Ltd.
91+ * Copyright (C) 2015-2016 Canonical, Ltd.
92 *
93 * This program is free software; you can redistribute it and/or modify
94 * it under the terms of the GNU General Public License as published by
95@@ -18,36 +18,52 @@
96 import Ubuntu.Components 1.3
97
98 Item {
99- readonly property alias running: internalTimer.running
100- property alias interval: internalTimer.interval
101+ id: root
102+
103+ readonly property bool running: delayTimer.running || inactivityTimer.running
104+ property int interval: 3000
105 property var page
106 property int lastInputTimestamp
107
108 function start() {
109- internalTimer.start();
110+ if (!delayTimer.running && !inactivityTimer.running) {
111+ delayTimer.start();
112+ }
113 }
114
115 ////
116
117 onLastInputTimestampChanged: {
118- if (internalTimer.running) {
119- internalTimer.restart();
120+ if (inactivityTimer.running) {
121+ inactivityTimer.restart();
122 }
123 }
124
125 Connections {
126 target: page
127 onIsReadyChanged: {
128- if (page.isReady && internalTimer.running) {
129- internalTimer.restart();
130- }
131- }
132- }
133-
134- Timer {
135- id: internalTimer
136-
137- interval: 3000
138+ if (page.isReady && inactivityTimer.running) {
139+ inactivityTimer.restart();
140+ }
141+ }
142+ onPausedChanged: {
143+ if (root.paused) {
144+ delayTimer.stop();
145+ inactivityTimer.stop();
146+ }
147+ }
148+ }
149+
150+ Timer {
151+ id: delayTimer
152+ interval: Math.max(root.interval - 3000, 0)
153+ onTriggered: inactivityTimer.start()
154+ }
155+
156+ Timer {
157+ id: inactivityTimer
158+
159+ interval: Math.min(root.interval, 3000)
160
161 onTriggered: {
162 if (page.isReady) {
163
164=== modified file 'qml/Tutorial/Tutorial.qml'
165--- qml/Tutorial/Tutorial.qml 2016-03-29 03:47:39 +0000
166+++ qml/Tutorial/Tutorial.qml 2016-06-10 14:15:49 +0000
167@@ -1,5 +1,5 @@
168 /*
169- * Copyright (C) 2014 Canonical, Ltd.
170+ * Copyright (C) 2014-2016 Canonical, Ltd.
171 *
172 * This program is free software; you can redistribute it and/or modify
173 * it under the terms of the GNU General Public License as published by
174@@ -26,17 +26,18 @@
175 Item {
176 id: root
177
178- property alias active: loader.active
179+ readonly property alias active: loader.active
180
181 property Item launcher
182 property Item panel
183 property Item stage
184 property string usageScenario
185- property bool paused
186- property bool keyboardVisible
187+ property bool paused // hide any existing tutorial and don't show new ones
188+ property bool delayed // don't show new tutorials
189 property int lastInputTimestamp
190
191 readonly property bool launcherEnabled: loader.item ? loader.item.launcherEnabled : true
192+ readonly property bool launcherLongSwipeEnabled: loader.item ? loader.item.launcherLongSwipeEnabled : true
193 readonly property bool spreadEnabled: loader.item ? loader.item.spreadEnabled : true
194 readonly property bool panelEnabled: loader.item ? loader.item.panelEnabled : true
195 readonly property bool running: loader.item ? loader.item.running : false
196@@ -85,8 +86,8 @@
197
198 Binding {
199 target: loader.item
200- property: "keyboardVisible"
201- value: root.keyboardVisible
202+ property: "delayed"
203+ value: root.delayed
204 }
205
206 Binding {
207
208=== removed file 'qml/Tutorial/TutorialBottom.qml'
209--- qml/Tutorial/TutorialBottom.qml 2016-04-26 07:32:40 +0000
210+++ qml/Tutorial/TutorialBottom.qml 1970-01-01 00:00:00 +0000
211@@ -1,124 +0,0 @@
212-/*
213- * Copyright (C) 2015 Canonical, Ltd.
214- *
215- * This program is free software; you can redistribute it and/or modify
216- * it under the terms of the GNU General Public License as published by
217- * the Free Software Foundation; version 3.
218- *
219- * This program is distributed in the hope that it will be useful,
220- * but WITHOUT ANY WARRANTY; without even the implied warranty of
221- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
222- * GNU General Public License for more details.
223- *
224- * You should have received a copy of the GNU General Public License
225- * along with this program. If not, see <http://www.gnu.org/licenses/>.
226- */
227-
228-import QtQuick 2.4
229-import Ubuntu.Components 1.3
230-import Ubuntu.Gestures 0.1
231-import Unity.Application 0.1
232-
233-TutorialPage {
234- id: root
235-
236- property string usageScenario
237- property var stage
238- property var application: null
239-
240- // This page is a bit fragile. It relies on knowing how the app beneath
241- // the shell will react to a drag. What we do is put a monitor-only DDA
242- // at the bottom of the page (so that we know when the drag is finished)
243- // and pass the events on through to the app. Thus, it sees the drag and
244- // brings its bottom edge up.
245- //
246- // Unfortunately, each app is on its own when implementing the bottom edge
247- // drag. Most share copied-and-pasted code right now, but they will
248- // eventually consolidate on a version of DirectionalDragArea that will
249- // land in the SDK (making our guessing job easier). Though, also in the
250- // future, this whole bottom tutorial component will also land in the SDK,
251- // rendering our version here obsolete.
252- //
253- // Anyway, for the moment, we base our guesses on the copied-and-pasted
254- // code used in several of the core apps and only bring this component
255- // up if we are in those core apps.
256-
257- readonly property real mainStageWidth: stage.width - sideStageWidth
258- readonly property real sideStageWidth: root.usageScenario === "tablet" && stage.sideStageVisible ?
259- stage.sideStageWidth : 0
260- readonly property bool isMainStageApp: usageScenario !== "tablet" ||
261- stage.stageFocusedSurface === ApplicationInfoInterface.MainStage
262- readonly property real dragAreaHeight: units.gu(3) // based on PageWithBottomEdge.qml
263- readonly property real targetDistance: height * 0.2 + dragAreaHeight // based on PageWithBottomEdge.qml
264-
265- opacityOverride: dragArea.dragging ? 1 - (dragArea.distance / targetDistance) : 1
266-
267- mouseArea {
268- anchors.bottomMargin: root.dragAreaHeight
269- }
270-
271- background {
272- sourceSize.height: 1916
273- sourceSize.width: 1080
274- source: Qt.resolvedUrl("graphics/background2.png")
275- rotation: 180
276- }
277-
278- arrow {
279- anchors.bottom: root.bottom
280- anchors.bottomMargin: units.gu(3)
281- anchors.horizontalCenter: label.horizontalCenter
282- anchors.horizontalCenterOffset: -(label.width - label.contentWidth) / 2
283- rotation: 90
284- }
285-
286- label {
287- text: !application ? "" :
288- application.appId === "address-book-app" ?
289- i18n.tr("Swipe up to add a contact") :
290- application.appId === "com.ubuntu.calculator_calculator" ?
291- i18n.tr("Swipe up for favorite calculations") :
292- application.appId === "dialer-app" ?
293- i18n.tr("Swipe up for recent calls") :
294- application.appId === "messaging-app" ?
295- i18n.tr("Swipe up to create a message") :
296- i18n.tr("Swipe up to manage the app") // shouldn't be used
297- anchors.bottom: arrow.top
298- anchors.bottomMargin: units.gu(3)
299- anchors.left: root.left
300- anchors.leftMargin: (label.width - label.contentWidth) / 2 + sideMargin +
301- (isMainStageApp ? 0 : mainStageWidth)
302- width: (isMainStageApp ? mainStageWidth : sideStageWidth) - sideMargin * 2
303-
304- readonly property real sideMargin: units.gu(4)
305- }
306-
307- // Watches drag events but does not intercept them, so that the app beneath
308- // will still drag the bottom edge up.
309- SwipeArea {
310- id: dragArea
311- grabGesture: false
312- direction: Direction.Upwards
313- anchors.left: parent.left
314- anchors.right: parent.right
315- anchors.bottom: parent.bottom
316- height: root.dragAreaHeight
317-
318- // Apps currently don't use DDA. DDA will stop a gesture if
319- // horizontal motion is detected. But our apps won't. So turn off
320- // that gesture cleverness on our part, it will only get us out of sync.
321- immediateRecognition: true
322- }
323-
324- MouseArea {
325- // A second mouse area because in tablet mode, we only want to let the
326- // user drag up on one of the stages, not both. So we want to cover
327- // the second bottom edge with an event eater.
328- enabled: root.usageScenario === "tablet"
329- height: root.dragAreaHeight
330- width: isMainStageApp ? sideStageWidth : mainStageWidth
331- anchors.bottom: parent.bottom
332- anchors.left: isMainStageApp ? undefined : parent.left
333- anchors.right: isMainStageApp ? parent.right : undefined
334- }
335-}
336
337=== modified file 'qml/Tutorial/TutorialContent.qml'
338--- qml/Tutorial/TutorialContent.qml 2016-03-29 03:47:39 +0000
339+++ qml/Tutorial/TutorialContent.qml 2016-06-10 14:15:49 +0000
340@@ -1,5 +1,5 @@
341 /*
342- * Copyright (C) 2013,2014 Canonical, Ltd.
343+ * Copyright (C) 2013-2016 Canonical, Ltd.
344 *
345 * This program is free software; you can redistribute it and/or modify
346 * it under the terms of the GNU General Public License as published by
347@@ -26,19 +26,21 @@
348 property Item panel
349 property Item stage
350 property string usageScenario
351- property bool paused
352- property bool keyboardVisible
353+ property bool paused: true // default to true so that we won't start until top level is all ready
354+ property bool delayed: true // same
355 property var lastInputTimestamp
356
357 readonly property bool launcherEnabled: !running
358 || tutorialLeftLoader.shown
359 || tutorialLeftLongLoader.shown
360+ readonly property bool launcherLongSwipeEnabled: tutorialLeftLongLoader.shown
361+ || tutorialLeftLongLoader.skipped
362 readonly property bool spreadEnabled: !running || tutorialRightLoader.shown
363 readonly property bool panelEnabled: !running || tutorialTopLoader.shown
364 readonly property bool running: tutorialLeftLoader.shown
365+ || tutorialLeftLongLoader.shown
366 || tutorialTopLoader.shown
367 || tutorialRightLoader.shown
368- || tutorialBottomLoader.shown
369
370 signal finished()
371
372@@ -57,16 +59,11 @@
373 root.usageScenario === "phone" ||
374 root.usageScenario === "tablet"
375
376- property var focusedApp: ApplicationManager.focusedApplicationId
377- ? ApplicationManager.findApplication(ApplicationManager.focusedApplicationId)
378- : null
379-
380 function haveShown(tutorialId) {
381 return AccountsService.demoEdgesCompleted.indexOf(tutorialId) != -1;
382 }
383
384- property bool endPointsFinished: tutorialRightLoader.skipped &&
385- tutorialBottomLoader.skipped
386+ property bool endPointsFinished: tutorialRightLoader.skipped
387 onEndPointsFinishedChanged: if (endPointsFinished) root.finish()
388 }
389
390@@ -88,15 +85,14 @@
391 hides: [launcher, panel.indicators]
392 paused: root.paused
393
394- isReady: !tutorialLeftLoader.skipped && !paused && !keyboardVisible &&
395- !tutorialBottomLoader.shown && !tutorialBottomLoader.mightShow
396+ isReady: !tutorialLeftLoader.skipped && !paused && !delayed
397
398- // Use an idle timer here, because when constructed, all our isReady variables will be false.
399- // Qml needs a moment to copy their values from Tutorial.qml. So we idle it and recheck.
400- Timer {
401+ InactivityTimer {
402 id: tutorialLeftTimer
403- interval: 0
404- onTriggered: if (tutorialLeft.isReady && !tutorialLeft.shown) tutorialLeft.show()
405+ objectName: "tutorialLeftTimer"
406+ interval: 20000
407+ lastInputTimestamp: root.lastInputTimestamp
408+ page: parent
409 }
410
411 onIsReadyChanged: if (isReady && !shown) tutorialLeftTimer.start()
412@@ -105,6 +101,40 @@
413 }
414
415 Loader {
416+ id: tutorialTopLoader
417+ objectName: "tutorialTopLoader"
418+ anchors.fill: parent
419+
420+ readonly property bool skipped: !d.mobileScenario || d.haveShown("top")
421+ readonly property bool shown: item && item.shown
422+ active: !skipped || (item && item.visible)
423+ onSkippedChanged: if (skipped && shown) item.hide()
424+
425+ sourceComponent: TutorialTop {
426+ id: tutorialTop
427+ objectName: "tutorialTop"
428+ anchors.fill: parent
429+ panel: root.panel
430+ hides: [launcher, panel.indicators]
431+ paused: root.paused
432+
433+ skipped: tutorialTopLoader.skipped
434+ isReady: tutorialLeftLoader.skipped && !skipped && !paused && !delayed
435+
436+ InactivityTimer {
437+ id: tutorialTopTimer
438+ objectName: "tutorialTopTimer"
439+ interval: 60000
440+ lastInputTimestamp: root.lastInputTimestamp
441+ page: parent
442+ }
443+
444+ onIsReadyChanged: if (isReady && !shown) tutorialTopTimer.start()
445+ onFinished: AccountsService.markDemoEdgeCompleted("top")
446+ }
447+ }
448+
449+ Loader {
450 id: tutorialLeftLongLoader
451 objectName: "tutorialLeftLongLoader"
452 anchors.fill: parent
453@@ -123,22 +153,15 @@
454 paused: root.paused
455
456 skipped: tutorialLeftLongLoader.skipped
457- isReady: tutorialLeftLoader.skipped && !skipped && !paused && !keyboardVisible &&
458- !tutorialBottomLoader.shown && !tutorialBottomLoader.mightShow
459+ isReady: tutorialTopLoader.skipped && !skipped && !paused && !delayed &&
460+ ApplicationManager.focusedApplicationId != "unity8-dash"
461
462- Timer {
463+ InactivityTimer {
464 id: tutorialLeftLongTimer
465 objectName: "tutorialLeftLongTimer"
466 interval: 5000
467- onTriggered: {
468- if (parent.isReady) {
469- if (!parent.shown) {
470- parent.show();
471- }
472- } else if (!parent.skipped) {
473- restart();
474- }
475- }
476+ lastInputTimestamp: root.lastInputTimestamp
477+ page: parent
478 }
479
480 onIsReadyChanged: if (isReady && !shown) tutorialLeftLongTimer.start()
481@@ -147,48 +170,6 @@
482 }
483
484 Loader {
485- id: tutorialTopLoader
486- objectName: "tutorialTopLoader"
487- anchors.fill: parent
488-
489- readonly property bool skipped: !d.mobileScenario || d.haveShown("top")
490- readonly property bool shown: item && item.shown
491- active: !skipped || (item && item.visible)
492- onSkippedChanged: if (skipped && shown) item.hide()
493-
494- sourceComponent: TutorialTop {
495- id: tutorialTop
496- objectName: "tutorialTop"
497- anchors.fill: parent
498- panel: root.panel
499- hides: [launcher, panel.indicators]
500- paused: root.paused
501-
502- skipped: tutorialTopLoader.skipped
503- isReady: tutorialLeftLongLoader.skipped && !skipped && !paused && !keyboardVisible &&
504- !tutorialBottomLoader.shown && !tutorialBottomLoader.mightShow
505-
506- // We fire 30s after left edge tutorial, with at least 3s of inactivity
507-
508- InactivityTimer {
509- id: tutorialTopInactivityTimer
510- lastInputTimestamp: root.lastInputTimestamp
511- page: parent
512- }
513-
514- Timer {
515- id: tutorialTopTimer
516- objectName: "tutorialTopTimer"
517- interval: 27000
518- onTriggered: tutorialTopInactivityTimer.start()
519- }
520-
521- onIsReadyChanged: if (isReady && !shown) tutorialTopTimer.start()
522- onFinished: AccountsService.markDemoEdgeCompleted("top")
523- }
524- }
525-
526- Loader {
527 id: tutorialRightLoader
528 objectName: "tutorialRightLoader"
529 anchors.fill: parent
530@@ -208,83 +189,19 @@
531 paused: root.paused
532
533 skipped: tutorialRightLoader.skipped
534- isReady: tutorialTopLoader.skipped && !skipped && !paused && !keyboardVisible &&
535- !tutorialBottomLoader.shown && !tutorialBottomLoader.mightShow &&
536- ApplicationManager.count >= 3
537+ isReady: tutorialTopLoader.skipped && !skipped && !paused && !delayed &&
538+ ApplicationManager.count >= 4
539
540 InactivityTimer {
541- id: tutorialRightInactivityTimer
542- objectName: "tutorialRightInactivityTimer"
543+ id: tutorialRightTimer
544+ objectName: "tutorialRightTimer"
545+ interval: 10000
546 lastInputTimestamp: root.lastInputTimestamp
547 page: parent
548 }
549
550- Connections {
551- target: d
552- onFocusedAppChanged: {
553- if (tutorialRight.isReady && !tutorialRight.shown && d.focusedApp
554- && d.focusedApp.state === ApplicationInfoInterface.Starting) {
555- tutorialRight.show();
556- }
557- }
558- }
559-
560- onIsReadyChanged: if (isReady && !shown) tutorialRightInactivityTimer.start()
561+ onIsReadyChanged: if (isReady && !shown) tutorialRightTimer.start()
562 onFinished: AccountsService.markDemoEdgeCompleted("right")
563 }
564 }
565-
566- Loader {
567- id: tutorialBottomLoader
568- objectName: "tutorialBottomLoader"
569- anchors.fill: parent
570-
571- // See TutorialBottom.qml for an explanation of why we only support
572- // certain apps.
573- readonly property var supportedApps: ["address-book-app",
574- "com.ubuntu.calculator_calculator",
575- "dialer-app",
576- "messaging-app"]
577- readonly property bool skipped: {
578- if (!d.mobileScenario) {
579- return true;
580- }
581- for (var i = 0; i < supportedApps.length; i++) {
582- if (!d.haveShown("bottom-" + supportedApps[i])) {
583- return false;
584- }
585- }
586- return true;
587- }
588- readonly property bool shown: item && item.shown
589- readonly property bool haveShownFocusedApp: d.focusedApp &&
590- d.haveShown("bottom-" + d.focusedApp.appId)
591- readonly property bool mightShow: !skipped && d.focusedApp &&
592- supportedApps.indexOf(d.focusedApp.appId) !== -1 &&
593- !haveShownFocusedApp
594- active: !skipped || (item && item.visible)
595- onHaveShownFocusedAppChanged: if (haveShownFocusedApp && shown) hide()
596- onSkippedChanged: if (skipped && shown) item.hide()
597-
598- sourceComponent: TutorialBottom {
599- id: tutorialBottom
600- objectName: "tutorialBottom"
601- anchors.fill: parent
602- hides: [launcher, panel.indicators]
603- paused: root.paused
604- usageScenario: root.usageScenario
605- stage: root.stage
606- application: d.focusedApp
607-
608- skipped: tutorialBottomLoader.skipped
609- isReady: !tutorialBottomLoader.skipped && !paused && !keyboardVisible &&
610- !tutorialLeftLoader.shown && !tutorialLeftLongLoader.shown &&
611- !tutorialTopLoader.shown && !tutorialRightLoader.shown &&
612- tutorialBottomLoader.mightShow &&
613- d.focusedApp.state === ApplicationInfoInterface.Running
614-
615- onIsReadyChanged: if (isReady && !shown) show()
616- onFinished: AccountsService.markDemoEdgeCompleted("bottom-" + d.focusedApp.appId)
617- }
618- }
619 }
620
621=== modified file 'qml/Tutorial/TutorialLeft.qml'
622--- qml/Tutorial/TutorialLeft.qml 2016-03-29 03:47:39 +0000
623+++ qml/Tutorial/TutorialLeft.qml 2016-06-10 14:15:49 +0000
624@@ -1,5 +1,5 @@
625 /*
626- * Copyright (C) 2015 Canonical, Ltd.
627+ * Copyright (C) 2015-2016 Canonical, Ltd.
628 *
629 * This program is free software; you can redistribute it and/or modify
630 * it under the terms of the GNU General Public License as published by
631@@ -44,7 +44,7 @@
632 }
633
634 label {
635- text: i18n.tr("Swipe from the left edge to open the launcher")
636+ text: i18n.tr("Short swipe from the left edge to open the launcher")
637 anchors.left: arrow.right
638 anchors.leftMargin: units.gu(3)
639 anchors.right: root.right
640
641=== modified file 'qml/Tutorial/TutorialLeftLong.qml'
642--- qml/Tutorial/TutorialLeftLong.qml 2016-02-19 17:40:20 +0000
643+++ qml/Tutorial/TutorialLeftLong.qml 2016-06-10 14:15:49 +0000
644@@ -23,7 +23,9 @@
645
646 property var launcher
647
648- opacityOverride: 1 - launcher.dragDistance / launcher.minimizeDistance
649+ // Unlike other tutorials, this one can't be skipped before we show it, so
650+ // only set opacityOverride if we're already shown.
651+ opacityOverride: shown ? 1 - launcher.dragDistance / launcher.minimizeDistance : 1
652
653 mouseArea {
654 anchors.leftMargin: launcher.dragAreaWidth
655
656=== modified file 'qml/Tutorial/TutorialPage.qml'
657--- qml/Tutorial/TutorialPage.qml 2016-03-29 03:47:39 +0000
658+++ qml/Tutorial/TutorialPage.qml 2016-06-10 14:15:49 +0000
659@@ -1,5 +1,5 @@
660 /*
661- * Copyright (C) 2013,2014 Canonical, Ltd.
662+ * Copyright (C) 2013-2016 Canonical, Ltd.
663 *
664 * This program is free software; you can redistribute it and/or modify
665 * it under the terms of the GNU General Public License as published by
666@@ -46,7 +46,7 @@
667 onOpacityOverrideChanged: {
668 if (opacityOverride <= 0) {
669 d.showOnUnpause = false;
670- hide();
671+ hideNow();
672 }
673 }
674 property real _showOpacity: 0
675
676=== modified file 'qml/Tutorial/TutorialRight.qml'
677--- qml/Tutorial/TutorialRight.qml 2016-03-31 03:15:03 +0000
678+++ qml/Tutorial/TutorialRight.qml 2016-06-10 14:15:49 +0000
679@@ -1,5 +1,5 @@
680 /*
681- * Copyright (C) 2015 Canonical, Ltd.
682+ * Copyright (C) 2015-2016 Canonical, Ltd.
683 *
684 * This program is free software; you can redistribute it and/or modify
685 * it under the terms of the GNU General Public License as published by
686@@ -53,7 +53,7 @@
687 label {
688 text: root.usageScenario === "desktop" ?
689 i18n.tr("Push your mouse against the right edge to view your open apps") :
690- i18n.tr("Short or long swipe from the right edge to view your open apps")
691+ i18n.tr("Swipe from the right edge to view your open apps")
692 anchors.right: arrow.left
693 anchors.rightMargin: units.gu(2) - (label.width - label.contentWidth)
694 anchors.verticalCenter: arrow.verticalCenter
695
696=== modified file 'qml/Tutorial/TutorialTop.qml'
697--- qml/Tutorial/TutorialTop.qml 2016-01-21 23:22:52 +0000
698+++ qml/Tutorial/TutorialTop.qml 2016-06-10 14:15:49 +0000
699@@ -1,5 +1,5 @@
700 /*
701- * Copyright (C) 2015 Canonical, Ltd.
702+ * Copyright (C) 2015-2016 Canonical, Ltd.
703 *
704 * This program is free software; you can redistribute it and/or modify
705 * it under the terms of the GNU General Public License as published by
706@@ -50,8 +50,7 @@
707 }
708
709 label {
710- text: d.landscape ? i18n.tr("Swipe from the top right edge to open the notification bar")
711- : i18n.tr("Swipe from the top edge to open the notification bar")
712+ text: i18n.tr("Swipe from the top edge to access notifications and quick settings")
713 anchors.top: arrow.bottom
714 anchors.topMargin: units.gu(3)
715 anchors.horizontalCenter: arrow.horizontalCenter
716
717=== modified file 'tests/qmltests/Tutorial/tst_Tutorial.qml'
718--- tests/qmltests/Tutorial/tst_Tutorial.qml 2016-05-02 07:57:07 +0000
719+++ tests/qmltests/Tutorial/tst_Tutorial.qml 2016-06-10 14:15:49 +0000
720@@ -1,5 +1,5 @@
721 /*
722- * Copyright (C) 2013,2014,2015 Canonical, Ltd.
723+ * Copyright (C) 2013-2016 Canonical, Ltd.
724 *
725 * This program is free software; you can redistribute it and/or modify
726 * it under the terms of the GNU General Public License as published by
727@@ -22,6 +22,7 @@
728 import Ubuntu.Components.ListItems 1.3
729 import Ubuntu.Telephony 0.1 as Telephony
730 import Unity.Application 0.1
731+import Unity.Notifications 1.0
732 import Unity.Test 0.1 as UT
733 import Utils 0.1
734
735@@ -55,6 +56,33 @@
736 phoneNumber: "+447812221111"
737 }
738
739+ Component {
740+ id: mockNotification
741+ QtObject {}
742+ }
743+
744+ ListModel {
745+ id: mockNotificationsModel
746+
747+ function getRaw(id) {
748+ return mockNotification.createObject(mockNotificationsModel)
749+ }
750+ }
751+
752+ function addNotification() {
753+ var n = {
754+ type: Notification.Confirmation,
755+ hints: {},
756+ summary: "",
757+ body: "",
758+ icon: "",
759+ secondaryIcon: "",
760+ actions: []
761+ };
762+
763+ mockNotificationsModel.append(n);
764+ }
765+
766 Component.onCompleted: {
767 // must set the mock mode before loading the Shell
768 LightDM.Greeter.mockMode = "single-pin";
769@@ -231,6 +259,8 @@
770 prepareShell();
771
772 var tutorialLeft = findChild(shell, "tutorialLeft");
773+ var tutorialLeftTimer = findInvisibleChild(tutorialLeft, "tutorialLeftTimer");
774+ tutorialLeftTimer.interval = 0;
775 tryCompare(tutorialLeft, "opacity", 1);
776 }
777
778@@ -260,6 +290,7 @@
779 // reload our test subject to get it in a fresh state once again
780 shellLoader.active = true;
781
782+ mockNotificationsModel.clear();
783 tryCompare(shellLoader, "status", Loader.Ready);
784 removeTimeConstraintsFromSwipeAreas(shellLoader.item);
785 }
786@@ -300,40 +331,41 @@
787 var tutorialTopTimer = findInvisibleChild(tutorialTop, "tutorialTopTimer");
788
789 tutorialTopTimer.interval = 1;
790- AccountsService.demoEdgesCompleted = ["left", "left-long"];
791+ AccountsService.demoEdgesCompleted = ["left"];
792
793 tryCompare(tutorialLeftLoader, "active", false);
794 tryCompare(tutorialTop, "shown", true);
795 tryCompare(tutorialTop, "opacity", 1);
796 }
797
798+ function openTutorialLeftLong() {
799+ var tutorialLeftLong = findChild(shell, "tutorialLeftLong");
800+ var tutorialLeftLongTimer = findChild(tutorialLeftLong, "tutorialLeftLongTimer");
801+
802+ AccountsService.demoEdgesCompleted = ["left", "top"];
803+ ApplicationManager.startApplication("gallery-app");
804+
805+ tutorialLeftLongTimer.interval = 1;
806+ tryCompare(tutorialLeftLong, "shown", true);
807+ tryCompare(tutorialLeftLong, "opacity", 1);
808+ }
809+
810 function openTutorialRight() {
811 var tutorialLeftLoader = findChild(shell, "tutorialLeftLoader");
812 var tutorialRight = findChild(shell, "tutorialRight");
813+ var tutorialRightTimer = findChild(tutorialRight, "tutorialRightTimer");
814
815- AccountsService.demoEdgesCompleted = ["left", "left-long", "top"];
816+ AccountsService.demoEdgesCompleted = ["left", "top", "left-long"];
817 ApplicationManager.startApplication("gallery-app");
818 ApplicationManager.startApplication("facebook-webapp");
819+ ApplicationManager.startApplication("camera-app");
820
821 tryCompare(tutorialLeftLoader, "active", false);
822+ tutorialRightTimer.interval = 1;
823 tryCompare(tutorialRight, "shown", true);
824 tryCompare(tutorialRight, "opacity", 1);
825 }
826
827- function openTutorialBottom() {
828- var tutorialLeftLoader = findChild(shell, "tutorialLeftLoader");
829- var tutorialBottom = findChild(shell, "tutorialBottom");
830-
831- AccountsService.demoEdgesCompleted = ["left", "left-long", "top", "right"];
832- tryCompare(tutorialLeftLoader, "active", false);
833-
834- ApplicationManager.startApplication("dialer-app");
835- ApplicationManager.requestFocusApplication("dialer-app");
836-
837- tryCompare(tutorialBottom, "shown", true);
838- tryCompare(tutorialBottom, "opacity", 1);
839- }
840-
841 function test_tutorialLeftEdges() {
842 var tutorial = findChild(shell, "tutorial");
843 var tutorialLeft = findChild(tutorial, "tutorialLeft");
844@@ -353,12 +385,12 @@
845
846 function test_tutorialLeftFinish() {
847 var tutorial = findChild(shell, "tutorial");
848- var tutorialLeft = findChild(tutorial, "tutorialLeft");
849+ var tutorialLeftLoader = findChild(tutorial, "tutorialLeftLoader");
850 var launcher = findChild(shell, "launcher");
851
852 touchFlick(shell, 0, halfHeight, halfWidth, halfHeight);
853
854- tryCompare(tutorialLeft, "shown", false);
855+ tryCompare(tutorialLeftLoader, "shown", false);
856 tryCompare(AccountsService, "demoEdgesCompleted", ["left"]);
857 tryCompare(launcher, "state", "visible");
858 }
859@@ -368,6 +400,7 @@
860 // letting go (i.e. not triggering the "progress" property of
861 // Launcher).
862 var tutorialLeft = findChild(shell, "tutorialLeft");
863+ var tutorialLeftLoader = findChild(shell, "tutorialLeftLoader");
864 var launcher = findChild(shell, "launcher");
865
866 // Confirm fade during drag
867@@ -384,31 +417,32 @@
868 // out much.
869 touchFlick(shell, 0, halfHeight, launcher.panelWidth * 0.4, halfHeight);
870 tryCompare(launcher, "state", ""); // should remain hidden
871- tryCompare(tutorialLeft, "shown", true); // and we should still be on left
872+ tryCompare(tutorialLeftLoader, "shown", true); // and we should still be on left
873
874
875 // Now drag out but not past launcher itself
876 touchFlick(shell, 0, halfHeight, launcher.panelWidth * 0.9, halfHeight);
877
878- tryCompare(tutorialLeft, "shown", false);
879+ tryCompare(tutorialLeftLoader, "shown", false);
880 tryCompare(AccountsService, "demoEdgesCompleted", ["left"]);
881 tryCompare(launcher, "state", "visible");
882 }
883
884- function test_tutorialLeftLongDrag() {
885- // Just confirm that a long drag ("dash" drag) doesn't confuse us
886-
887- // So that we actually switch to dash and launcher hides
888+ function test_tutorialLeftLongFinish() {
889+ AccountsService.demoEdgesCompleted = ["left", "top"];
890+
891+ var tutorialLeftLongTimer = findInvisibleChild(shell, "tutorialLeftLongTimer");
892+ tutorialLeftLongTimer.interval = 1;
893+
894 ApplicationManager.startApplication("gallery-app");
895
896- var launcher = findChild(shell, "launcher");
897- var tutorialLeft = findChild(shell, "tutorialLeftLoader");
898- verify(tutorialLeft);
899+ var tutorialLeftLongLoader = findChild(shell, "tutorialLeftLongLoader");
900+ tryCompare(tutorialLeftLongLoader, "shown", true);
901
902 touchFlick(shell, 0, halfHeight, shell.width, halfHeight);
903
904- tryCompare(tutorialLeft, "shown", false);
905- tryCompare(AccountsService, "demoEdgesCompleted", ["left", "left-long"]);
906+ tryCompare(tutorialLeftLongLoader, "shown", false);
907+ tryCompare(AccountsService, "demoEdgesCompleted", ["left", "top", "left-long"]);
908 }
909
910 function test_tutorialLeftAutoSkipped() {
911@@ -423,6 +457,24 @@
912 tryCompare(AccountsService, "demoEdgesCompleted", ["left"]);
913 }
914
915+ function test_tutorialLongLeftSwipeDisabled() {
916+ // Test that a long left swipe is disabled until we get to or pass
917+ // the long left tutorial.
918+ var tutorial = findChild(shell, "tutorial");
919+
920+ verify(!tutorial.launcherLongSwipeEnabled);
921+
922+ openTutorialLeftLong();
923+ verify(tutorial.launcherLongSwipeEnabled);
924+
925+ openTutorialRight();
926+ verify(tutorial.launcherLongSwipeEnabled);
927+
928+ AccountsService.demoEdges = false;
929+ tryCompare(tutorial, "running", false);
930+ verify(tutorial.launcherLongSwipeEnabled);
931+ }
932+
933 function test_tutorialTopEdges() {
934 var tutorial = findChild(shell, "tutorial");
935 var tutorialTop = findChild(tutorial, "tutorialTop");
936@@ -444,14 +496,14 @@
937
938 function test_tutorialTopFinish() {
939 var tutorial = findChild(shell, "tutorial");
940- var tutorialTop = findChild(tutorial, "tutorialTop");
941+ var tutorialTopLoader = findChild(tutorial, "tutorialTopLoader");
942 var panel = findChild(shell, "panel");
943
944 openTutorialTop();
945 touchFlick(shell, halfWidth, 0, halfWidth, shell.height);
946
947- tryCompare(tutorialTop, "shown", false);
948- tryCompare(AccountsService, "demoEdgesCompleted", ["left", "left-long", "top"]);
949+ tryCompare(tutorialTopLoader, "shown", false);
950+ tryCompare(AccountsService, "demoEdgesCompleted", ["left", "top"]);
951 tryCompare(panel.indicators, "fullyOpened", true);
952 }
953
954@@ -477,12 +529,12 @@
955
956 var tutorialLeftLoader = findChild(shell, "tutorialLeftLoader");
957 var tutorialTop = findChild(shell, "tutorialTop");
958- AccountsService.demoEdgesCompleted = ["left", "left-long"];
959+ AccountsService.demoEdgesCompleted = ["left"];
960 tryCompare(tutorialLeftLoader, "active", false);
961 verify(!tutorialTop.shown);
962
963 touchFlick(shell, halfWidth, 0, halfWidth, shell.height);
964- tryCompare(AccountsService, "demoEdgesCompleted", ["left", "left-long", "top"]);
965+ tryCompare(AccountsService, "demoEdgesCompleted", ["left", "top"]);
966 }
967
968 function test_tutorialRightEdges() {
969@@ -505,15 +557,11 @@
970 }
971
972 function test_tutorialRightFinish() {
973- var tutorial = findChild(shell, "tutorial");
974- var tutorialRight = findChild(tutorial, "tutorialRight");
975- var stage = findChild(shell, "stage");
976-
977 openTutorialRight();
978 touchFlick(shell, shell.width, halfHeight, 0, halfHeight);
979
980- tryCompare(tutorialRight, "shown", false);
981- tryCompare(AccountsService, "demoEdgesCompleted", ["left", "left-long", "top", "right"]);
982+ tryCompare(AccountsService, "demoEdgesCompleted", ["left", "top", "left-long", "right"]);
983+ tryCompare(AccountsService, "demoEdges", false);
984 }
985
986 function test_tutorialRightShortDrag() {
987@@ -537,17 +585,18 @@
988 // Test that if we exit the top tutorial, we don't immediately
989 // jump into right tutorial.
990 var tutorialRight = findChild(shell, "tutorialRight");
991- var tutorialRightTimer = findInvisibleChild(tutorialRight, "tutorialRightInactivityTimer");
992+ var tutorialRightTimer = findInvisibleChild(tutorialRight, "tutorialRightTimer");
993
994- tutorialRightTimer.interval = 1;
995 openTutorialTop();
996 ApplicationManager.startApplication("gallery-app");
997 ApplicationManager.startApplication("facebook-webapp");
998- tryCompare(ApplicationManager, "count", 3);
999+ ApplicationManager.startApplication("camera-app");
1000+ tryCompare(ApplicationManager, "count", 4);
1001
1002- AccountsService.demoEdgesCompleted = ["left", "left-long", "top"];
1003- verify(tutorialRightTimer.running, true);
1004+ AccountsService.demoEdgesCompleted = ["left", "top", "left-long"];
1005+ verify(tutorialRightTimer.running);
1006 verify(!tutorialRight.shown);
1007+ tutorialRightTimer.interval = 1;
1008 tryCompare(tutorialRight, "shown", true);
1009 }
1010
1011@@ -555,112 +604,11 @@
1012 // Test that we skip the tutorial if user uses right edge themselves
1013
1014 var tutorialLeftLoader = findChild(shell, "tutorialLeftLoader");
1015- AccountsService.demoEdgesCompleted = ["left", "left-long"];
1016+ AccountsService.demoEdgesCompleted = ["left"];
1017 tryCompare(tutorialLeftLoader, "active", false);
1018
1019 touchFlick(shell, shell.width, halfHeight, 0, halfHeight);
1020- tryCompare(AccountsService, "demoEdgesCompleted", ["left", "left-long", "right"]);
1021- }
1022-
1023- function test_tutorialBottomEdges() {
1024- var tutorial = findChild(shell, "tutorial");
1025- var tutorialBottom = findChild(tutorial, "tutorialBottom");
1026- var tutorialLabel = findChild(tutorialBottom, "tutorialLabel");
1027- var launcher = findChild(shell, "launcher");
1028- var stage = findChild(shell, "stage");
1029- var panel = findChild(shell, "panel");
1030-
1031- openTutorialBottom();
1032-
1033- tryCompare(tutorial, "running", true);
1034- verify(!tutorial.launcherEnabled);
1035- verify(!tutorial.spreadEnabled);
1036- verify(!tutorial.panelEnabled);
1037- verify(tutorialBottom.shown);
1038- verify(!launcher.available);
1039- verify(!stage.spreadEnabled);
1040- verify(!panel.indicators.available);
1041- compare(tutorialLabel.text, "Swipe up for recent calls");
1042- }
1043-
1044- function test_tutorialBottomFinish() {
1045- var tutorial = findChild(shell, "tutorial");
1046- var tutorialBottom = findChild(tutorial, "tutorialBottom");
1047-
1048- openTutorialBottom();
1049- touchFlick(shell, halfWidth, shell.height, halfWidth, halfHeight);
1050-
1051- tryCompare(tutorialBottom, "shown", false);
1052- tryCompare(AccountsService, "demoEdgesCompleted", ["left", "left-long", "top", "right", "bottom-dialer-app"]);
1053-
1054- // OK, we did one, just confirm that when all are done, we mark whole tutorial as done.
1055- verify(AccountsService.demoEdges);
1056- AccountsService.demoEdgesCompleted = ["left", "left-long", "top", "right",
1057- "bottom-address-book-app",
1058- "bottom-com.ubuntu.calculator_calculator",
1059- "bottom-dialer-app",
1060- "bottom-messaging-app"];
1061- verify(!AccountsService.demoEdges);
1062- }
1063-
1064- function test_tutorialBottomAppearsBeforeRight() {
1065- // Confirm that if bottom edge and right edge would appear on the
1066- // the same app open, bottom edge appears first. (this is a lightly
1067- // edited version of openTutorialRight)
1068- var tutorialLeftLoader = findChild(shell, "tutorialLeftLoader");
1069- var tutorialRight = findChild(shell, "tutorialRight");
1070- var tutorialBottom = findChild(shell, "tutorialBottom");
1071-
1072- AccountsService.demoEdgesCompleted = ["left", "left-long", "top"];
1073- ApplicationManager.startApplication("gallery-app");
1074- ApplicationManager.startApplication("dialer-app");
1075-
1076- tryCompare(tutorialLeftLoader, "active", false);
1077- tryCompare(tutorialBottom, "shown", true);
1078- tryCompare(tutorialBottom, "opacity", 1);
1079- tryCompare(tutorialRight, "visible", false);
1080- }
1081-
1082- function test_tutorialBottomOnlyCoversSideStageOnTablet() {
1083- loadShell("tablet");
1084-
1085- var tutorialBottom = findChild(shell, "tutorialBottom");
1086- var targetHeight = shell.height - units.gu(4);
1087- var mainStageX = units.gu(20);
1088- var sideStageX = shell.width - units.gu(20);
1089-
1090- WindowStateStorage.saveStage("dialer-app", ApplicationInfoInterface.SideStage);
1091- openTutorialBottom();
1092-
1093- touchFlick(shell, mainStageX, shell.height, mainStageX, targetHeight, true, false);
1094- compare(tutorialBottom.opacity, 1);
1095- touchFlick(shell, mainStageX, shell.height, mainStageX, targetHeight, false, true);
1096-
1097- touchFlick(shell, sideStageX, shell.height, sideStageX, targetHeight, true, false);
1098- verify(tutorialBottom.opacity < 1);
1099- touchFlick(shell, sideStageX, shell.height, sideStageX, targetHeight, false, true);
1100- }
1101-
1102- function test_tutorialBottomOnlyCoversMainStageOnTablet() {
1103- loadShell("tablet");
1104-
1105- var tutorialBottom = findChild(shell, "tutorialBottom");
1106- var targetHeight = shell.height - units.gu(4);
1107- var mainStageX = units.gu(20);
1108- var sideStageX = shell.width - units.gu(20);
1109-
1110- WindowStateStorage.saveStage("notes-app", ApplicationInfoInterface.SideStage);
1111- ApplicationManager.startApplication("notes-app");
1112-
1113- openTutorialBottom();
1114-
1115- touchFlick(shell, sideStageX, shell.height, sideStageX, targetHeight, true, false);
1116- compare(tutorialBottom.opacity, 1);
1117- touchFlick(shell, sideStageX, shell.height, sideStageX, targetHeight, false, true);
1118-
1119- touchFlick(shell, mainStageX, shell.height, mainStageX, targetHeight, true, false);
1120- verify(tutorialBottom.opacity < 1);
1121- touchFlick(shell, mainStageX, shell.height, mainStageX, targetHeight, false, true);
1122+ tryCompare(AccountsService, "demoEdgesCompleted", ["left", "right"]);
1123 }
1124
1125 function test_activeCallInterruptsTutorial() {
1126@@ -678,31 +626,6 @@
1127 verify(!tutorialLeft.paused);
1128 }
1129
1130- function test_dialerInterruptionWithNoOverlappingTutorials() {
1131- var tutorialLeft = findChild(shell, "tutorialLeft");
1132- var tutorialBottom = findChild(shell, "tutorialBottom");
1133- verify(tutorialLeft.shown);
1134-
1135- // Start call, hiding left tutorial
1136- callManager.foregroundCall = phoneCall;
1137- tryCompare(tutorialLeft, "shown", false);
1138-
1139- // Start dialer app
1140- ApplicationManager.startApplication("dialer-app");
1141- tryCompare(ApplicationManager, "focusedApplicationId", "dialer-app");
1142- verify(!tutorialBottom.shown);
1143-
1144- // Dismiss call, bottom tutorial should appear
1145- callManager.foregroundCall = null;
1146- tryCompare(tutorialBottom, "shown", true);
1147- verify(!tutorialLeft.shown);
1148-
1149- // Get rid of bottom tutorial, left should now be shown
1150- touchFlick(shell, halfWidth, shell.height, halfWidth, halfHeight);
1151- tryCompare(tutorialBottom, "shown", false);
1152- tryCompare(tutorialLeft, "shown", true);
1153- }
1154-
1155 function test_greeterInterruptsTutorial() {
1156 var tutorialLeft = findChild(shell, "tutorialLeft");
1157 verify(tutorialLeft.shown);
1158@@ -738,7 +661,7 @@
1159 verify(!tutorialRight.isReady);
1160 verify(!tutorialRight.shown);
1161 verify(!tutorialRight.paused);
1162- compare(AccountsService.demoEdgesCompleted, ["left", "left-long", "top"]);
1163+ compare(AccountsService.demoEdgesCompleted, ["left", "top", "left-long"]);
1164 }
1165
1166 function test_desktopOnlyShowsTutorialRight() {
1167@@ -746,17 +669,22 @@
1168
1169 var tutorialLeftLoader = findChild(shell, "tutorialLeftLoader");
1170 var tutorialTopLoader = findChild(shell, "tutorialTopLoader");
1171+ var tutorialLeftLongLoader = findChild(shell, "tutorialLeftLongLoader");
1172 var tutorialRightLoader = findChild(shell, "tutorialRightLoader");
1173- var tutorialBottomLoader = findChild(shell, "tutorialBottomLoader");
1174 verify(!tutorialLeftLoader.active);
1175 verify(!tutorialTopLoader.active);
1176+ verify(!tutorialLeftLongLoader.active);
1177 verify(tutorialRightLoader.active);
1178- verify(!tutorialBottomLoader.active);
1179 compare(AccountsService.demoEdgesCompleted, []);
1180
1181+ var tutorialRightTimer = findInvisibleChild(tutorialRightLoader, "tutorialRightTimer");
1182+ tutorialRightTimer.interval = 1;
1183+
1184 ApplicationManager.startApplication("dialer-app");
1185 ApplicationManager.startApplication("camera-app");
1186+ ApplicationManager.startApplication("facebook-webapp");
1187 tryCompare(tutorialRightLoader.item, "isReady", true);
1188+
1189 tryCompare(tutorialRightLoader, "shown", true);
1190 }
1191
1192@@ -764,8 +692,11 @@
1193 loadShell("desktop");
1194
1195 var tutorialRight = findChild(shell, "tutorialRight");
1196+ var tutorialRightTimer = findInvisibleChild(tutorialRight, "tutorialRightTimer");
1197+ tutorialRightTimer.interval = 1;
1198 ApplicationManager.startApplication("dialer-app");
1199 ApplicationManager.startApplication("camera-app");
1200+ ApplicationManager.startApplication("facebook-webapp");
1201 tryCompare(tutorialRight, "shown", true);
1202
1203 var stage = findChild(shell, "stage");
1204@@ -789,24 +720,60 @@
1205 verify(tutorialLeft.shown);
1206 }
1207
1208- function test_oskPreventsTutorial() {
1209- var surface = SurfaceManager.inputMethodSurface;
1210- var inputMethod = findInvisibleChild(shell, "inputMethod");
1211-
1212- AccountsService.demoEdges = false;
1213- surface.setState(Mir.RestoredState);
1214- tryCompare(inputMethod, "state", "shown");
1215-
1216- var tutorial = findChild(shell, "tutorial");
1217- tryCompare(tutorial, "keyboardVisible", true);
1218-
1219- AccountsService.demoEdges = true;
1220- var tutorialLeft = findChild(shell, "tutorialLeft");
1221- verify(!tutorialLeft.shown);
1222-
1223- surface.setState(Mir.MinimizedState);
1224- tryCompare(inputMethod, "state", "hidden");
1225- tryCompare(tutorialLeft, "shown", false);
1226+ function test_oskDelaysTutorial() {
1227+ var tutorial = findChild(shell, "tutorial");
1228+ verify(!tutorial.delayed);
1229+
1230+ SurfaceManager.inputMethodSurface.setState(Mir.RestoredState);
1231+
1232+ tryCompare(tutorial, "delayed", true);
1233+ }
1234+
1235+ function test_notificationDelaysTutorial() {
1236+ var tutorial = findChild(shell, "tutorial");
1237+ verify(!tutorial.delayed);
1238+
1239+ var notifications = findChild(shell, "notificationList");
1240+ notifications.model = mockNotificationsModel;
1241+ addNotification(); // placeholder
1242+ addNotification();
1243+
1244+ tryCompare(tutorial, "delayed", true);
1245+ }
1246+
1247+ function test_dialogDelaysTutorial() {
1248+ var tutorial = findChild(shell, "tutorial");
1249+ verify(!tutorial.delayed);
1250+
1251+ var dialogs = findChild(shell, "dialogs");
1252+ dialogs.showPowerDialog();
1253+
1254+ verify(tutorial.delayed);
1255+ }
1256+
1257+ function test_delayedTutorial() {
1258+ var tutorial = findChild(shell, "tutorial");
1259+ var tutorialTop = findChild(tutorial, "tutorialTop");
1260+ var tutorialTopTimer = findChild(tutorialTop, "tutorialTopTimer");
1261+
1262+ // Get top tutorial ready
1263+ AccountsService.demoEdgesCompleted = ["left"];
1264+ verify(tutorialTop.isReady);
1265+ verify(tutorialTopTimer.running);
1266+
1267+ // Confirm that we become unready when delayed, but timer still goes
1268+ tutorial.delayed = true;
1269+ verify(!tutorialTop.isReady);
1270+ verify(tutorialTopTimer.running);
1271+
1272+ // Confirm that we don't open the tutorial when delayed
1273+ tutorialTopTimer.interval = 1;
1274+ wait(5);
1275+ verify(!tutorialTop.shown);
1276+
1277+ // Confirm we go back to normal when undelayed
1278+ tutorial.delayed = false;
1279+ tryCompare(tutorialTop, "shown", true);
1280 }
1281
1282 function test_accountsServiceSettings() {
1283@@ -820,7 +787,9 @@
1284 AccountsService.demoEdges = true;
1285 tutorialLeft = findChild(shell, "tutorialLeft");
1286 verify(tutorialLeft != null);
1287- tryCompare(tutorialLeft, "shown", true);
1288+
1289+ var tutorialLeftTimer = findChild(tutorialLeft, "tutorialLeftTimer");
1290+ verify(tutorialLeftTimer.running);
1291 }
1292 }
1293 }
1294
1295=== modified file 'tests/qmltests/tst_Shell.qml'
1296--- tests/qmltests/tst_Shell.qml 2016-05-27 13:51:53 +0000
1297+++ tests/qmltests/tst_Shell.qml 2016-06-10 14:15:49 +0000
1298@@ -1233,13 +1233,10 @@
1299
1300 function test_wizardEarlyExit() {
1301 Wizard.System.wizardEnabled = true;
1302- AccountsService.demoEdges = true;
1303 loadShell("phone");
1304
1305 var wizard = findChild(shell, "wizard");
1306- var tutorial = findChild(shell, "tutorial");
1307 tryCompare(wizard, "active", true);
1308- tryCompare(tutorial, "running", true);
1309 tryCompareFunction(function() { return topLevelSurfaceList.applicationAt(0).appId; }, "unity8-dash");
1310
1311 // Make sure we stay running when there's no top level window (can happen for
1312@@ -1252,14 +1249,12 @@
1313
1314 tryCompare(topLevelSurfaceList, "count", 0);
1315 compare(wizard.shown, true);
1316- compare(tutorial.running, true);
1317
1318 // And make sure we stay running when dash comes back again
1319 var dashSurfaceId = topLevelSurfaceList.nextId;
1320 ApplicationManager.startApplication(dashApplication.appId);
1321 waitUntilAppWindowIsFullyLoaded(dashSurfaceId);
1322 compare(wizard.shown, true);
1323- compare(tutorial.running, true);
1324
1325 // And make sure we stop when some other surface shows app
1326 var gallerySurfaceId = topLevelSurfaceList.nextId;
1327@@ -1267,12 +1262,7 @@
1328 waitUntilAppWindowIsFullyLoaded(gallerySurfaceId);
1329 tryCompareFunction(function() { return topLevelSurfaceList.applicationAt(0).appId; }, "gallery-app");
1330 compare(wizard.shown, false);
1331- compare(tutorial.running, false);
1332- tryCompare(AccountsService, "demoEdges", false);
1333 tryCompare(Wizard.System, "wizardEnabled", false);
1334-
1335- var tutorialLeft = findChild(tutorial, "tutorialLeft");
1336- compare(tutorialLeft, null); // should be destroyed with tutorial
1337 }
1338
1339 function test_tutorialPausedDuringGreeter() {

Subscribers

People subscribed via source and target branches