on xenial help sign in
Drop bottom tutorials
commit4ab97e819b6280bc5b05c7569e3147c98a170272 authorMichael Terry <michael.terry@canonical.com> dateThu 28 Apr 2016, 11:36 (10 years ago) parentd7e5694
3 files changed+5−331
qml/Tutorial/TutorialBottom.qml−124 qml/Tutorial/TutorialContent.qml+5−65 tests/qmltests/Tutorial/tst_Tutorial.qml−142
qml/Tutorial/TutorialBottom.qmldeleted−124
@@ -1,124 +0,0 @@
1−/*
2− * Copyright (C) 2015 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.4
18−import Ubuntu.Components 1.3
19−import Ubuntu.Gestures 0.1
20−import Unity.Application 0.1
21−
22−TutorialPage {
23− id: root
24−
25− property string usageScenario
26− property var stage
27− property var application: null
28−
29− // This page is a bit fragile. It relies on knowing how the app beneath
30− // the shell will react to a drag. What we do is put a monitor-only DDA
31− // at the bottom of the page (so that we know when the drag is finished)
32− // and pass the events on through to the app. Thus, it sees the drag and
33− // brings its bottom edge up.
34− //
35− // Unfortunately, each app is on its own when implementing the bottom edge
36− // drag. Most share copied-and-pasted code right now, but they will
37− // eventually consolidate on a version of DirectionalDragArea that will
38− // land in the SDK (making our guessing job easier). Though, also in the
39− // future, this whole bottom tutorial component will also land in the SDK,
40− // rendering our version here obsolete.
41− //
42− // Anyway, for the moment, we base our guesses on the copied-and-pasted
43− // code used in several of the core apps and only bring this component
44− // up if we are in those core apps.
45−
46− readonly property real mainStageWidth: stage.width - sideStageWidth
47− readonly property real sideStageWidth: root.usageScenario === "tablet" && stage.sideStageVisible ?
48− stage.sideStageWidth : 0
49− readonly property bool isMainStageApp: usageScenario !== "tablet" ||
50− stage.stageFocusedSurface === ApplicationInfoInterface.MainStage
51− readonly property real dragAreaHeight: units.gu(3) // based on PageWithBottomEdge.qml
52− readonly property real targetDistance: height * 0.2 + dragAreaHeight // based on PageWithBottomEdge.qml
53−
54− opacityOverride: dragArea.dragging ? 1 - (-dragArea.distance / targetDistance) : 1
55−
56− mouseArea {
57− anchors.bottomMargin: root.dragAreaHeight
58− }
59−
60− background {
61− sourceSize.height: 1916
62− sourceSize.width: 1080
63− source: Qt.resolvedUrl("graphics/background2.png")
64− rotation: 180
65− }
66−
67− arrow {
68− anchors.bottom: root.bottom
69− anchors.bottomMargin: units.gu(3)
70− anchors.horizontalCenter: label.horizontalCenter
71− anchors.horizontalCenterOffset: -(label.width - label.contentWidth) / 2
72− rotation: 90
73− }
74−
75− label {
76− text: !application ? "" :
77− application.appId === "address-book-app" ?
78− i18n.tr("Swipe up to add a contact") :
79− application.appId === "com.ubuntu.calculator_calculator" ?
80− i18n.tr("Swipe up for favorite calculations") :
81− application.appId === "dialer-app" ?
82− i18n.tr("Swipe up for recent calls") :
83− application.appId === "messaging-app" ?
84− i18n.tr("Swipe up to create a message") :
85− i18n.tr("Swipe up to manage the app") // shouldn't be used
86− anchors.bottom: arrow.top
87− anchors.bottomMargin: units.gu(3)
88− anchors.left: root.left
89− anchors.leftMargin: (label.width - label.contentWidth) / 2 + sideMargin +
90− (isMainStageApp ? 0 : mainStageWidth)
91− width: (isMainStageApp ? mainStageWidth : sideStageWidth) - sideMargin * 2
92−
93− readonly property real sideMargin: units.gu(4)
94− }
95−
96− // Watches drag events but does not intercept them, so that the app beneath
97− // will still drag the bottom edge up.
98− DirectionalDragArea {
99− id: dragArea
100− monitorOnly: true
101− direction: Direction.Upwards
102− anchors.left: parent.left
103− anchors.right: parent.right
104− anchors.bottom: parent.bottom
105− height: root.dragAreaHeight
106−
107− // Apps currently don't use DDA. DDA will stop a gesture if
108− // horizontal motion is detected. But our apps won't. So turn off
109− // that gesture cleverness on our part, it will only get us out of sync.
110− immediateRecognition: true
111− }
112−
113− MouseArea {
114− // A second mouse area because in tablet mode, we only want to let the
115− // user drag up on one of the stages, not both. So we want to cover
116− // the second bottom edge with an event eater.
117− enabled: root.usageScenario === "tablet"
118− height: root.dragAreaHeight
119− width: isMainStageApp ? sideStageWidth : mainStageWidth
120− anchors.bottom: parent.bottom
121− anchors.left: isMainStageApp ? undefined : parent.left
122− anchors.right: isMainStageApp ? parent.right : undefined
123− }
124−}
qml/Tutorial/TutorialContent.qml+5−65
@@ -38,7 +38,6 @@ Item {
3838 readonly property bool running: tutorialLeftLoader.shown
3939 || tutorialTopLoader.shown
4040 || tutorialRightLoader.shown
41− || tutorialBottomLoader.shown
4241
4342 signal finished()
4443
@@ -65,8 +64,7 @@ Item {
6564 return AccountsService.demoEdgesCompleted.indexOf(tutorialId) != -1;
6665 }
6766
68− property bool endPointsFinished: tutorialRightLoader.skipped &&
69− tutorialBottomLoader.skipped
67+ property bool endPointsFinished: tutorialRightLoader.skipped
7068 onEndPointsFinishedChanged: if (endPointsFinished) root.finish()
7169 }
7270
@@ -88,8 +86,7 @@ Item {
8886 hides: [launcher, panel.indicators]
8987 paused: root.paused
9088
91− isReady: !tutorialLeftLoader.skipped && !paused && !keyboardVisible &&
92− !tutorialBottomLoader.shown && !tutorialBottomLoader.mightShow
89+ isReady: !tutorialLeftLoader.skipped && !paused && !keyboardVisible
9390
9491 // Use an idle timer here, because when constructed, all our isReady variables will be false.
9592 // Qml needs a moment to copy their values from Tutorial.qml. So we idle it and recheck.
@@ -123,8 +120,7 @@ Item {
123120 paused: root.paused
124121
125122 skipped: tutorialLeftLongLoader.skipped
126− isReady: tutorialLeftLoader.skipped && !skipped && !paused && !keyboardVisible &&
127− !tutorialBottomLoader.shown && !tutorialBottomLoader.mightShow
123+ isReady: tutorialLeftLoader.skipped && !skipped && !paused && !keyboardVisible
128124
129125 Timer {
130126 id: tutorialLeftLongTimer
@@ -165,8 +161,7 @@ Item {
165161 paused: root.paused
166162
167163 skipped: tutorialTopLoader.skipped
168− isReady: tutorialLeftLongLoader.skipped && !skipped && !paused && !keyboardVisible &&
169− !tutorialBottomLoader.shown && !tutorialBottomLoader.mightShow
164+ isReady: tutorialLeftLongLoader.skipped && !skipped && !paused && !keyboardVisible
170165
171166 // We fire 30s after left edge tutorial, with at least 3s of inactivity
172167
@@ -208,8 +203,7 @@ Item {
208203 paused: root.paused
209204
210205 skipped: tutorialRightLoader.skipped
211− isReady: tutorialTopLoader.skipped && !skipped && !paused && !keyboardVisible &&
212− !tutorialBottomLoader.shown && !tutorialBottomLoader.mightShow &&
206+ isReady: tutorialTopLoader.skipped && !skipped && !paused && !keyboardVisible
213207 ApplicationManager.count >= 3
214208
215209 InactivityTimer {
@@ -233,58 +227,4 @@ Item {
233227 onFinished: AccountsService.markDemoEdgeCompleted("right")
234228 }
235229 }
236−
237− Loader {
238− id: tutorialBottomLoader
239− objectName: "tutorialBottomLoader"
240− anchors.fill: parent
241−
242− // See TutorialBottom.qml for an explanation of why we only support
243− // certain apps.
244− readonly property var supportedApps: ["address-book-app",
245− "com.ubuntu.calculator_calculator",
246− "dialer-app",
247− "messaging-app"]
248− readonly property bool skipped: {
249− if (!d.mobileScenario) {
250− return true;
251− }
252− for (var i = 0; i < supportedApps.length; i++) {
253− if (!d.haveShown("bottom-" + supportedApps[i])) {
254− return false;
255− }
256− }
257− return true;
258− }
259− readonly property bool shown: item && item.shown
260− readonly property bool haveShownFocusedApp: d.focusedApp &&
261− d.haveShown("bottom-" + d.focusedApp.appId)
262− readonly property bool mightShow: !skipped && d.focusedApp &&
263− supportedApps.indexOf(d.focusedApp.appId) !== -1 &&
264− !haveShownFocusedApp
265− active: !skipped || (item && item.visible)
266− onHaveShownFocusedAppChanged: if (haveShownFocusedApp && shown) hide()
267− onSkippedChanged: if (skipped && shown) item.hide()
268−
269− sourceComponent: TutorialBottom {
270− id: tutorialBottom
271− objectName: "tutorialBottom"
272− anchors.fill: parent
273− hides: [launcher, panel.indicators]
274− paused: root.paused
275− usageScenario: root.usageScenario
276− stage: root.stage
277− application: d.focusedApp
278−
279− skipped: tutorialBottomLoader.skipped
280− isReady: !tutorialBottomLoader.skipped && !paused && !keyboardVisible &&
281− !tutorialLeftLoader.shown && !tutorialLeftLongLoader.shown &&
282− !tutorialTopLoader.shown && !tutorialRightLoader.shown &&
283− tutorialBottomLoader.mightShow &&
284− d.focusedApp.state === ApplicationInfoInterface.Running
285−
286− onIsReadyChanged: if (isReady && !shown) show()
287− onFinished: AccountsService.markDemoEdgeCompleted("bottom-" + d.focusedApp.appId)
288− }
289− }
290230}
tests/qmltests/Tutorial/tst_Tutorial.qml−142
@@ -320,20 +320,6 @@ Rectangle {
320320 tryCompare(tutorialRight, "opacity", 1);
321321 }
322322
323− function openTutorialBottom() {
324− var tutorialLeftLoader = findChild(shell, "tutorialLeftLoader");
325− var tutorialBottom = findChild(shell, "tutorialBottom");
326−
327− AccountsService.demoEdgesCompleted = ["left", "left-long", "top", "right"];
328− tryCompare(tutorialLeftLoader, "active", false);
329−
330− ApplicationManager.startApplication("dialer-app");
331− ApplicationManager.requestFocusApplication("dialer-app");
332−
333− tryCompare(tutorialBottom, "shown", true);
334− tryCompare(tutorialBottom, "opacity", 1);
335− }
336−
337323 function test_tutorialLeftEdges() {
338324 var tutorial = findChild(shell, "tutorial");
339325 var tutorialLeft = findChild(tutorial, "tutorialLeft");
@@ -562,107 +548,6 @@ Rectangle {
562548 tryCompare(AccountsService, "demoEdgesCompleted", ["left", "left-long", "right"]);
563549 }
564550
565− function test_tutorialBottomEdges() {
566− var tutorial = findChild(shell, "tutorial");
567− var tutorialBottom = findChild(tutorial, "tutorialBottom");
568− var tutorialLabel = findChild(tutorialBottom, "tutorialLabel");
569− var launcher = findChild(shell, "launcher");
570− var stage = findChild(shell, "stage");
571− var panel = findChild(shell, "panel");
572−
573− openTutorialBottom();
574−
575− tryCompare(tutorial, "running", true);
576− verify(!tutorial.launcherEnabled);
577− verify(!tutorial.spreadEnabled);
578− verify(!tutorial.panelEnabled);
579− verify(tutorialBottom.shown);
580− verify(!launcher.available);
581− verify(!stage.spreadEnabled);
582− verify(!panel.indicators.available);
583− compare(tutorialLabel.text, "Swipe up for recent calls");
584− }
585−
586− function test_tutorialBottomFinish() {
587− var tutorial = findChild(shell, "tutorial");
588− var tutorialBottom = findChild(tutorial, "tutorialBottom");
589−
590− openTutorialBottom();
591− touchFlick(shell, halfWidth, shell.height, halfWidth, halfHeight);
592−
593− tryCompare(tutorialBottom, "shown", false);
594− tryCompare(AccountsService, "demoEdgesCompleted", ["left", "left-long", "top", "right", "bottom-dialer-app"]);
595−
596− // OK, we did one, just confirm that when all are done, we mark whole tutorial as done.
597− verify(AccountsService.demoEdges);
598− AccountsService.demoEdgesCompleted = ["left", "left-long", "top", "right",
599− "bottom-address-book-app",
600− "bottom-com.ubuntu.calculator_calculator",
601− "bottom-dialer-app",
602− "bottom-messaging-app"];
603− verify(!AccountsService.demoEdges);
604− }
605−
606− function test_tutorialBottomAppearsBeforeRight() {
607− // Confirm that if bottom edge and right edge would appear on the
608− // the same app open, bottom edge appears first. (this is a lightly
609− // edited version of openTutorialRight)
610− var tutorialLeftLoader = findChild(shell, "tutorialLeftLoader");
611− var tutorialRight = findChild(shell, "tutorialRight");
612− var tutorialBottom = findChild(shell, "tutorialBottom");
613−
614− AccountsService.demoEdgesCompleted = ["left", "left-long", "top"];
615− ApplicationManager.startApplication("gallery-app");
616− ApplicationManager.startApplication("dialer-app");
617−
618− tryCompare(tutorialLeftLoader, "active", false);
619− tryCompare(tutorialBottom, "shown", true);
620− tryCompare(tutorialBottom, "opacity", 1);
621− tryCompare(tutorialRight, "visible", false);
622− }
623−
624− function test_tutorialBottomOnlyCoversSideStageOnTablet() {
625− loadShell("tablet");
626−
627− var tutorialBottom = findChild(shell, "tutorialBottom");
628− var targetHeight = shell.height - units.gu(4);
629− var mainStageX = units.gu(20);
630− var sideStageX = shell.width - units.gu(20);
631−
632− WindowStateStorage.saveStage("dialer-app", ApplicationInfoInterface.SideStage);
633− openTutorialBottom();
634−
635− touchFlick(shell, mainStageX, shell.height, mainStageX, targetHeight, true, false);
636− compare(tutorialBottom.opacity, 1);
637− touchFlick(shell, mainStageX, shell.height, mainStageX, targetHeight, false, true);
638−
639− touchFlick(shell, sideStageX, shell.height, sideStageX, targetHeight, true, false);
640− verify(tutorialBottom.opacity < 1);
641− touchFlick(shell, sideStageX, shell.height, sideStageX, targetHeight, false, true);
642− }
643−
644− function test_tutorialBottomOnlyCoversMainStageOnTablet() {
645− loadShell("tablet");
646−
647− var tutorialBottom = findChild(shell, "tutorialBottom");
648− var targetHeight = shell.height - units.gu(4);
649− var mainStageX = units.gu(20);
650− var sideStageX = shell.width - units.gu(20);
651−
652− WindowStateStorage.saveStage("notes-app", ApplicationInfoInterface.SideStage);
653− ApplicationManager.startApplication("notes-app");
654−
655− openTutorialBottom();
656−
657− touchFlick(shell, sideStageX, shell.height, sideStageX, targetHeight, true, false);
658− compare(tutorialBottom.opacity, 1);
659− touchFlick(shell, sideStageX, shell.height, sideStageX, targetHeight, false, true);
660−
661− touchFlick(shell, mainStageX, shell.height, mainStageX, targetHeight, true, false);
662− verify(tutorialBottom.opacity < 1);
663− touchFlick(shell, mainStageX, shell.height, mainStageX, targetHeight, false, true);
664− }
665−
666551 function test_activeCallInterruptsTutorial() {
667552 var tutorialLeft = findChild(shell, "tutorialLeft");
668553 verify(tutorialLeft.shown);
@@ -678,31 +563,6 @@ Rectangle {
678563 verify(!tutorialLeft.paused);
679564 }
680565
681− function test_dialerInterruptionWithNoOverlappingTutorials() {
682− var tutorialLeft = findChild(shell, "tutorialLeft");
683− var tutorialBottom = findChild(shell, "tutorialBottom");
684− verify(tutorialLeft.shown);
685−
686− // Start call, hiding left tutorial
687− callManager.foregroundCall = phoneCall;
688− tryCompare(tutorialLeft, "shown", false);
689−
690− // Start dialer app
691− ApplicationManager.startApplication("dialer-app");
692− tryCompare(ApplicationManager, "focusedApplicationId", "dialer-app");
693− verify(!tutorialBottom.shown);
694−
695− // Dismiss call, bottom tutorial should appear
696− callManager.foregroundCall = null;
697− tryCompare(tutorialBottom, "shown", true);
698− verify(!tutorialLeft.shown);
699−
700− // Get rid of bottom tutorial, left should now be shown
701− touchFlick(shell, halfWidth, shell.height, halfWidth, halfHeight);
702− tryCompare(tutorialBottom, "shown", false);
703− tryCompare(tutorialLeft, "shown", true);
704− }
705−
706566 function test_greeterInterruptsTutorial() {
707567 var tutorialLeft = findChild(shell, "tutorialLeft");
708568 verify(tutorialLeft.shown);
@@ -747,11 +607,9 @@ Rectangle {
747607 var tutorialLeftLoader = findChild(shell, "tutorialLeftLoader");
748608 var tutorialTopLoader = findChild(shell, "tutorialTopLoader");
749609 var tutorialRightLoader = findChild(shell, "tutorialRightLoader");
750− var tutorialBottomLoader = findChild(shell, "tutorialBottomLoader");
751610 verify(!tutorialLeftLoader.active);
752611 verify(!tutorialTopLoader.active);
753612 verify(tutorialRightLoader.active);
754− verify(!tutorialBottomLoader.active);
755613 compare(AccountsService.demoEdgesCompleted, []);
756614
757615 ApplicationManager.startApplication("dialer-app");