Commit 2b424064 authored by Akihiro Ota's avatar Akihiro Ota Committed by Commit Bot

ChromeVox OOBE Tutorial

This change:
1. Fills in content for the tutorial given in the OOBE.
2. Automatically opens the OOBE tutorial if ChromeVox is started from
the OOBE. Only do this if the
--enable-experimental-accessibility-chromevox-tutorial flag is enabled.
3. Adds a Panel method for creating the interactive tutorial. The logic
for this function existed prior to this change; we add this method for
better cleanliness and readability.

Bug: 1075752
Change-Id: I3aaefb2a934cde078747bfee105c1427af305400
AX-Relnotes: N/A
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2330048
Commit-Queue: Akihiro Ota <akihiroota@chromium.org>
Reviewed-by: default avatarDavid Tseng <dtseng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#796205}
parent 81b4743d
......@@ -183,6 +183,24 @@ Background = class extends ChromeVoxState {
onTtsInterrupted() {}
};
new ProgressPlayer();
chrome.commandLinePrivate.hasSwitch(
'enable-experimental-accessibility-chromevox-tutorial', (enabled) => {
if (!enabled) {
return;
}
chrome.loginState.getSessionState((sessionState) => {
// If starting ChromeVox from OOBE, start the ChromeVox tutorial.
// Use a timeout to allow ChromeVox to initialize first.
if (sessionState ===
chrome.loginState.SessionState.IN_OOBE_SCREEN) {
setTimeout(() => {
(new PanelCommand(PanelCommandType.TUTORIAL)).send();
}, 1000);
}
});
});
}
/**
......
......@@ -101,7 +101,6 @@ h1 {
hidden$="[[ shouldHideMainMenu(activeScreen) ]]">
<h1 id="mainMenuHeader" tabindex="-1">[[ chooseYourExperience ]]</h1>
<div id="mainMenuButtons">
<cr-button id="oobeButton" on-click="chooseCurriculum">OOBE</cr-button>
<cr-button id="newUserButton" on-click="chooseCurriculum">
[[ newUser ]]
</cr-button>
......@@ -125,8 +124,8 @@ h1 {
hidden$="[[ shouldHideLessonContainer(activeScreen) ]]">
<!-- Use lessonData object to create all lessons -->
<template is="dom-repeat" items="[[ lessonData ]]" as="lesson"
index-as="index">
<template id="lessonTemplate" is="dom-repeat" items="[[ lessonData ]]"
as="lesson" index-as="index">
<tutorial-lesson
lesson-num="[[ index ]]"
title="[[ lesson.title ]]"
......@@ -161,13 +160,18 @@ h1 {
[[ nextLesson ]]
</cr-button>
<cr-button on-click="showLessonMenu"
hidden$="[[ !shouldHideLessonMenu(activeScreen) ]]">
hidden$="[[ shouldHideLessonMenuButton(activeScreen) ]]">
[[ lessonMenu ]]
</cr-button>
<cr-button on-click="showMainMenu"
hidden$="[[ !shouldHideMainMenu(activeScreen) ]]">
hidden$="[[ shouldHideMainMenuButton(activeScreen) ]]">
[[ mainMenu ]]
</cr-button>
<cr-button on-click="showFirstLesson"
hidden$="[[
shouldHideRestartBasicOrientationButton(activeLessonIndex) ]]">
[[ restartBasicOrientation ]]
</cr-button>
<cr-button on-click="exit">[[ exitTutorial ]]</cr-button>
</div>
</div>
......
......@@ -84,6 +84,10 @@ export const TutorialLesson = Polymer({
'A lesson must have an element which specifies tabindex.');
}
focus.focus();
if (!focus.isEqualNode(this.shadowRoot.activeElement)) {
// Call show() again if we weren't able to focus the target element.
setTimeout(this.show.bind(this), 500);
}
},
/** @private */
......
......@@ -189,7 +189,6 @@ Panel = class {
/** @private {boolean} */
Panel.iTutorialEnabled_ = false;
chrome.commandLinePrivate.hasSwitch(
'enable-experimental-accessibility-chromevox-tutorial', (enabled) => {
Panel.iTutorialEnabled_ = enabled;
......@@ -1136,64 +1135,23 @@ Panel = class {
* @param {string=} opt_page Show a specific page.
*/
static onTutorial(opt_page) {
// Change the url fragment to 'fullscreen', which signals the native
// host code to make the window fullscreen, revealing the menus.
if (Panel.iTutorialEnabled_) {
if ($('i-tutorial') === null) {
// Load resources if this is the first time opening the tutorial.
const tutorialScript = document.createElement('script');
tutorialScript.src = '../i_tutorial/i_tutorial.js';
tutorialScript.setAttribute('type', 'module');
const lessonScript = document.createElement('script');
lessonScript.src = '../i_tutorial/tutorial_lesson.js';
lessonScript.setAttribute('type', 'module');
document.body.appendChild(tutorialScript);
document.body.appendChild(lessonScript);
// Create tutorial container and element.
const tutorialContainer = document.createElement('div');
tutorialContainer.setAttribute('id', 'i-tutorial-container');
tutorialContainer.hidden = true;
const tutorialElement = document.createElement('i-tutorial');
tutorialElement.setAttribute('id', 'i-tutorial');
tutorialContainer.appendChild(tutorialElement);
document.body.appendChild(tutorialContainer);
Panel.iTutorial = tutorialElement;
// Add listeners. These are custom events fired from custom components.
$('i-tutorial').addEventListener('closetutorial', (evt) => {
// Ensure UserActionMonitor is destroyed before closing tutorial.
const background =
chrome.extension
.getBackgroundPage()['ChromeVoxState']['instance'];
background.destroyUserActionMonitor();
Panel.onCloseTutorial();
});
$('i-tutorial').addEventListener('requestspeech', (evt) => {
const text = evt.detail.text;
const background = chrome.extension.getBackgroundPage();
const cvox = background['ChromeVox'];
cvox.tts.speak(
text, background.QueueMode.FLUSH, {'doNotInterrupt': true});
});
$('i-tutorial').addEventListener('startinteractivemode', (evt) => {
const actions = evt.detail.actions;
const background =
chrome.extension
.getBackgroundPage()['ChromeVoxState']['instance'];
background.createUserActionMonitor(actions, () => {
background.destroyUserActionMonitor();
Panel.iTutorial.showNextLesson();
});
});
if (!$('i-tutorial')) {
const curriculum = Panel.sessionState ===
chrome.loginState.SessionState.IN_OOBE_SCREEN ?
'oobe' :
null;
Panel.createITutorial(curriculum);
}
Panel.setMode(Panel.Mode.FULLSCREEN_I_TUTORIAL);
if (Panel.iTutorial.show) {
Panel.iTutorial.show();
}
return;
}
Panel.setMode(Panel.Mode.FULLSCREEN_TUTORIAL);
switch (opt_page) {
case 'updateNotes':
Panel.tutorial_.updateNotes();
......@@ -1203,6 +1161,64 @@ Panel = class {
}
}
/**
* Creates an <i-tutorial> element and adds it to the dom.
* @param {(string|null)} curriculum
*/
static createITutorial(curriculum) {
const tutorialScript = document.createElement('script');
tutorialScript.src = '../i_tutorial/i_tutorial.js';
tutorialScript.setAttribute('type', 'module');
const lessonScript = document.createElement('script');
lessonScript.src = '../i_tutorial/tutorial_lesson.js';
lessonScript.setAttribute('type', 'module');
document.body.appendChild(tutorialScript);
document.body.appendChild(lessonScript);
// Create tutorial container and element.
const tutorialContainer = document.createElement('div');
tutorialContainer.setAttribute('id', 'i-tutorial-container');
tutorialContainer.hidden = true;
const tutorialElement = document.createElement('i-tutorial');
tutorialElement.setAttribute('id', 'i-tutorial');
if (curriculum) {
tutorialElement.curriculum = curriculum;
}
tutorialContainer.appendChild(tutorialElement);
document.body.appendChild(tutorialContainer);
Panel.iTutorial = tutorialElement;
// Add listeners. These are custom events fired from custom components.
$('i-tutorial').addEventListener('closetutorial', (evt) => {
// Ensure UserActionMonitor is destroyed before closing tutorial.
const background =
chrome.extension.getBackgroundPage()['ChromeVoxState']['instance'];
background.destroyUserActionMonitor();
Panel.onCloseTutorial();
});
$('i-tutorial').addEventListener('requestspeech', (evt) => {
const text = evt.detail.text;
const background = chrome.extension.getBackgroundPage();
const cvox = background['ChromeVox'];
cvox.tts.speak(
text, background.QueueMode.INTERJECT, {'doNotInterrupt': true});
});
$('i-tutorial').addEventListener('startinteractivemode', (evt) => {
const actions = evt.detail.actions;
const background =
chrome.extension.getBackgroundPage()['ChromeVoxState']['instance'];
background.createUserActionMonitor(actions, () => {
background.destroyUserActionMonitor();
Panel.iTutorial.showNextLesson();
});
});
$('i-tutorial').addEventListener('stopinteractivemode', (evt) => {
const background =
chrome.extension.getBackgroundPage()['ChromeVoxState']['instance'];
background.destroyUserActionMonitor();
});
}
/**
* Move to the next page in the tutorial.
*/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment