2 * Copyright (C) 2013,2014 Canonical, Ltd.
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.
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.
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/>.
18import Ubuntu.Components 1.3
19import AccountsService 0.1
20import Unity.Application 0.1
25 property Item launcher
28 property string usageScenario
30 property bool keyboardVisible
31 property var lastInputTimestamp
33 readonly property bool launcherEnabled: !running
34 || tutorialLeftLoader.shown
35 || tutorialLeftLongLoader.shown
36 readonly property bool spreadEnabled: !running || tutorialRightLoader.shown
37 readonly property bool panelEnabled: !running || tutorialTopLoader.shown
38 readonly property bool running: tutorialLeftLoader.shown
39 || tutorialTopLoader.shown
40 || tutorialRightLoader.shown
41 || tutorialBottomLoader.shown
54 // We allow "" because it is briefly empty on startup, and we don't
55 // want to improperly skip any mobile tutorials.
56 property bool mobileScenario: root.usageScenario === "" ||
57 root.usageScenario === "phone" ||
58 root.usageScenario === "tablet"
60 property var focusedApp: ApplicationManager.focusedApplicationId
61 ? ApplicationManager.findApplication(ApplicationManager.focusedApplicationId)
64 function haveShown(tutorialId) {
65 return AccountsService.demoEdgesCompleted.indexOf(tutorialId) != -1;
68 property bool endPointsFinished: tutorialRightLoader.skipped &&
69 tutorialBottomLoader.skipped
70 onEndPointsFinishedChanged: if (endPointsFinished) root.finish()
74 id: tutorialLeftLoader
75 objectName: "tutorialLeftLoader"
78 readonly property bool skipped: !d.mobileScenario || d.haveShown("left")
79 readonly property bool shown: item && item.shown
80 active: !skipped || (item && item.visible)
81 onSkippedChanged: if (skipped && shown) item.hide()
83 sourceComponent: TutorialLeft {
85 objectName: "tutorialLeft"
87 launcher: root.launcher
88 hides: [launcher, panel.indicators]
91 isReady: !tutorialLeftLoader.skipped && !paused && !keyboardVisible
93 // Use an idle timer here, because when constructed, all our isReady variables will be false.
94 // Qml needs a moment to copy their values from Tutorial.qml. So we idle it and recheck.
98 onTriggered: if (tutorialLeft.isReady && !tutorialLeft.shown) tutorialLeft.show()
101 onIsReadyChanged: if (isReady && !shown) tutorialLeftTimer.start()
102 onFinished: AccountsService.markDemoEdgeCompleted("left")
107 id: tutorialLeftLongLoader
108 objectName: "tutorialLeftLongLoader"
111 readonly property bool skipped: !d.mobileScenario || d.haveShown("left-long")
112 readonly property bool shown: item && item.shown
113 active: !skipped || (item && item.visible)
114 onSkippedChanged: if (skipped && shown) item.hide()
116 sourceComponent: TutorialLeftLong {
118 objectName: "tutorialLeftLong"
120 launcher: root.launcher
121 hides: [launcher, panel.indicators]
124 skipped: tutorialLeftLongLoader.skipped
125 isReady: tutorialLeftLoader.skipped && !skipped && !paused && !keyboardVisible &&
126 !tutorialBottomLoader.shown && !tutorialBottomLoader.mightShow
129 id: tutorialLeftLongTimer
130 objectName: "tutorialLeftLongTimer"
133 if (parent.isReady) {
137 } else if (!parent.skipped) {
143 onIsReadyChanged: if (isReady && !shown) tutorialLeftLongTimer.start()
144 onFinished: AccountsService.markDemoEdgeCompleted("left-long")
149 id: tutorialTopLoader
150 objectName: "tutorialTopLoader"
153 readonly property bool skipped: !d.mobileScenario || d.haveShown("top")
154 readonly property bool shown: item && item.shown
155 active: !skipped || (item && item.visible)
156 onSkippedChanged: if (skipped && shown) item.hide()
158 sourceComponent: TutorialTop {
160 objectName: "tutorialTop"
163 hides: [launcher, panel.indicators]
166 skipped: tutorialTopLoader.skipped
167 isReady: tutorialLeftLongLoader.skipped && !skipped && !paused && !keyboardVisible &&
168 !tutorialBottomLoader.shown && !tutorialBottomLoader.mightShow
170 // We fire 30s after left edge tutorial, with at least 3s of inactivity
173 id: tutorialTopInactivityTimer
174 lastInputTimestamp: root.lastInputTimestamp
180 objectName: "tutorialTopTimer"
182 onTriggered: tutorialTopInactivityTimer.start()
185 onIsReadyChanged: if (isReady && !shown) tutorialTopTimer.start()
186 onFinished: AccountsService.markDemoEdgeCompleted("top")
191 id: tutorialRightLoader
192 objectName: "tutorialRightLoader"
195 readonly property bool skipped: d.haveShown("right")
196 readonly property bool shown: item && item.shown
197 active: !skipped || (item && item.visible)
198 onSkippedChanged: if (skipped && shown) item.hide()
200 sourceComponent: TutorialRight {
202 objectName: "tutorialRight"
205 usageScenario: root.usageScenario
206 hides: [launcher, panel.indicators]
209 skipped: tutorialRightLoader.skipped
210 isReady: tutorialTopLoader.skipped && !skipped && !paused && !keyboardVisible &&
211 !tutorialBottomLoader.shown && !tutorialBottomLoader.mightShow &&
212 ApplicationManager.count >= 3
215 id: tutorialRightInactivityTimer
216 objectName: "tutorialRightInactivityTimer"
217 lastInputTimestamp: root.lastInputTimestamp
223 onFocusedAppChanged: {
224 if (tutorialRight.isReady && !tutorialRight.shown && d.focusedApp
225 && d.focusedApp.state === ApplicationInfoInterface.Starting) {
226 tutorialRight.show();
231 onIsReadyChanged: if (isReady && !shown) tutorialRightInactivityTimer.start()
232 onFinished: AccountsService.markDemoEdgeCompleted("right")
237 id: tutorialBottomLoader
238 objectName: "tutorialBottomLoader"
241 // See TutorialBottom.qml for an explanation of why we only support
243 readonly property var supportedApps: ["address-book-app",
244 "com.ubuntu.calculator_calculator",
247 readonly property bool skipped: {
248 if (!d.mobileScenario) {
251 for (var i = 0; i < supportedApps.length; i++) {
252 if (!d.haveShown("bottom-" + supportedApps[i])) {
258 readonly property bool shown: item && item.shown
259 readonly property bool haveShownFocusedApp: d.focusedApp &&
260 d.haveShown("bottom-" + d.focusedApp.appId)
261 readonly property bool mightShow: !skipped && d.focusedApp &&
262 supportedApps.indexOf(d.focusedApp.appId) !== -1 &&
264 active: !skipped || (item && item.visible)
265 onHaveShownFocusedAppChanged: if (haveShownFocusedApp && shown) hide()
266 onSkippedChanged: if (skipped && shown) item.hide()
268 sourceComponent: TutorialBottom {
270 objectName: "tutorialBottom"
272 hides: [launcher, panel.indicators]
274 usageScenario: root.usageScenario
276 application: d.focusedApp
278 skipped: tutorialBottomLoader.skipped
279 isReady: !tutorialBottomLoader.skipped && !paused && !keyboardVisible &&
280 !tutorialTopLoader.shown && !tutorialRightLoader.shown &&
281 tutorialBottomLoader.mightShow &&
282 d.focusedApp.state === ApplicationInfoInterface.Running
284 onIsReadyChanged: if (isReady && !shown) show()
285 onFinished: AccountsService.markDemoEdgeCompleted("bottom-" + d.focusedApp.appId)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list