|
| 1 | +# Announcer Library |
| 2 | + |
| 3 | +The `Announcer` library allows for relevant information to be voiced along the focus path of the application. By passing the focus path to `Announcer.onFocusChange` the function traverses the `_focusPath` property collecting strings or promises of strings to announce to the user. The array of information is passed to a SpeechEngine which is responsible for converting the text to speech. By default we use the [speechSynthesis API](https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesis), but you can replace this by overwriting `Announcer._textToSpeech`. |
| 4 | + |
| 5 | +Note: The speechSynth api has some known problems:<br /> |
| 6 | +https://stackoverflow.com/questions/39391502/js-speechsynthesis-problems-with-the-cancel-method<br /> |
| 7 | +https://stackoverflow.com/questions/23483990/speechsynthesis-api-onend-callback-not-working<br /> |
| 8 | + |
| 9 | +This class does its best to work around these issues, but speech synth api can randomly fail. |
| 10 | + |
| 11 | +## Usage |
| 12 | + |
| 13 | +```js |
| 14 | +import { Router, {Announcer} = Accessibility } from '@lightningjs/sdk'; |
| 15 | +export default class App extends Router.App { |
| 16 | + ... |
| 17 | + _focusChange() { |
| 18 | + Announcer.onFocusChange(this.application._focusPath); |
| 19 | + } |
| 20 | +} |
| 21 | +``` |
| 22 | + |
| 23 | +Set `Announcer.debug = true` to see console tables of the output as shown below. |
| 24 | + |
| 25 | +| Index | Component | Property | Value | |
| 26 | +| ----- | ------------ | ---------- | ------------------------------------------------ | |
| 27 | +| 0 | BrowsePage-1 | Title | Free to Me | |
| 28 | +| 1 | Grid | Title | | |
| 29 | +| 2 | Rows | Title | | |
| 30 | +| 3 | Row | Title | Popular Movies - Free to Me | |
| 31 | +| 4 | Items | Title | | |
| 32 | +| 5 | TileItem | Title | Teenage Mutant Ninja Turtles: Out of the Shadows | |
| 33 | +| 6 | Metadata | Announce | Promise | |
| 34 | +| 7 | Metadata | No Context | | |
| 35 | +| 8 | TileItem | Context | 1 of 5 | |
| 36 | +| 9 | Items | No Context | | |
| 37 | +| 10 | Row | No Context | | |
| 38 | +| 11 | Rows | No Context | | |
| 39 | +| 12 | Grid | No Context | | |
| 40 | +| 13 | BrowsePage-1 | Context | PAUSE-2 Press LEFT or RIGHT to | |
| 41 | + |
| 42 | +The `Announcer` will travel through the `_focusPath` looking for `component.announce` then `component.title` properties. After collecting those properties it reverses the `_focusPath` looking for `component.announceContext`. |
| 43 | + |
| 44 | +### SpeechType |
| 45 | + |
| 46 | +All of the properties may return values compatible with the following recursive type definition: |
| 47 | + |
| 48 | +``` |
| 49 | +SpeechType = string | Array<SpeechType> | Promise<SpeechType> | () => SpeechType |
| 50 | +``` |
| 51 | + |
| 52 | +At its simplest, you may return a string or an array of strings. Promises and functions that return SpeechType values may be used as necessary for advanced/asyncronous use cases. |
| 53 | + |
| 54 | +#### Examples |
| 55 | + |
| 56 | +```js |
| 57 | + get announce() { |
| 58 | + return [ |
| 59 | + 'Despicable Me', |
| 60 | + Promise.resolve([ |
| 61 | + ['2020', 'Rated PG'], |
| 62 | + Promise.resolve('Steve Carell, Miranda Cosgrove, Kristen Wiig, Pierre Coffin'), |
| 63 | + () => 'A description of the movie' |
| 64 | + ]) |
| 65 | + ]; |
| 66 | + } |
| 67 | + |
| 68 | + get announceContext() { |
| 69 | + return 'Press LEFT or RIGHT to review items'; |
| 70 | + } |
| 71 | +``` |
| 72 | + |
| 73 | +## Inserting a pause |
| 74 | + |
| 75 | +You may also use `PAUSE-#` to pause speech for # seconds before saying the next string. |
| 76 | + |
| 77 | +```js |
| 78 | + get announceContext() { |
| 79 | + return ['PAUSE-2.5', 'Hello there!']; |
| 80 | + } |
| 81 | +``` |
| 82 | + |
| 83 | +## API |
| 84 | +### Properties |
| 85 | + |
| 86 | +| name | type | readonly | description | |
| 87 | +| ---------------- | ------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | |
| 88 | +| enabled | boolean | false | default true - flag to turn on or off Announcer | |
| 89 | +| announcerTimeout | number | false | By default the announcer only gets information about what changed between focus paths. The announcerTimeout resets the cache to announce the full focus path when the user has been inactive a certain amount of time. Default value is 5 minutes. | |
| 90 | + |
| 91 | +### Methods |
| 92 | + |
| 93 | +| name | args | description | |
| 94 | +| ----------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | |
| 95 | +| speak | | Performs a manual announce | |
| 96 | +| | `announcement` | See _SpeechType_ above | |
| 97 | +| | `options` | Object containing one or more boolean flags: <br/><ul><li>append - Appends announcement to the currently announcing series.</li><li>notification - Speaks out notification and then performs $announcerRefresh.</li></ul> | |
| 98 | +| clearPrevFocus | `depth` | Clears the last known focusPath - depth can trim known focusPath | |
| 99 | +| cancel | none | Cancels current speaking | |
| 100 | +| setupTimers | `options` | Object containing: <br/><ul><li>focusDebounce - default amount of time to wait after last input before focus change announcing will occur.</li><li>focusChangeTimeout - Amount of time with no input before full announce will occur on next focusChange</li></ul> | |
0 commit comments