OO-PG0016
Plug-In: Read Outline Rows
This plug-in will read the text of the selected outline rows.
The plug-in includes these optional preferences:
- Include the recitation of each row’s note (if any).
- Include the recitation of each row’s position identifier, ex: 2.2.1
- Read the entire outline, instead of just the selected rows (default).
During the execution of the plug-in, an alert dialog will be presented. Click the alert button at any time to halt the text-to-speech process.
| Video: Read Outline Rows |
| This plug-in will read the text of the selected outline rows. |
|
|
Return to: OmniOutliner Plug-In Collection
Read Outline Rows
/*{"type": "action","targets": ["omnioutliner"],"author": "Otto Automator","identifier": "com.omni-automation.oo.read-outline-rows","version": "1.4","description": "This plug-in will read the text of the selected rows or the entire outline. There is also an option to automatically include the recitation of the row’s note.","label": "Read Outline Rows","shortLabel": "Read Outline Rows","paletteLabel": "Read Outline Rows","image": "person.wave.2.fill"}*/(() => {var preferences = new Preferences() // NO ID = PLUG-IN IDfunction createUtterance(textToSpeak){langCode = Speech.Voice.currentLanguageCodevoiceObj = Speech.Voice.withLanguage(langCode)utterance = new Speech.Utterance(textToSpeak)utterance.voice = voiceObjutterance.rate = Speech.Utterance.defaultSpeechRatereturn utterance}function genPositionID(item){nums = item.ancestors.map(x => 1 + x.index)nums.reverse().push(item.index + 1)return nums.join(".")}const action = new PlugIn.Action(async function(selection, sender){try {var synthesizer = new Speech.Synthesizer()shouldIdentifyRow = preferences.readBoolean("shouldIdentifyRow")if(!shouldIdentifyRow){shouldIdentifyRow = false}console.log("shouldIdentifyRow", shouldIdentifyRow)shouldReadNotes = preferences.readBoolean("shouldReadNotes")if(!shouldReadNotes){shouldReadNotes = false}console.log("shouldReadNotes", shouldReadNotes)shouldReadOutline = preferences.readBoolean("shouldReadOutline")if(!shouldReadOutline){shouldReadOutline = false}console.log("shouldReadOutline", shouldReadOutline)checkSwitchFieldA = new Form.Field.Checkbox("shouldIdentifyRow","Speak each row’s positional identifier",shouldIdentifyRow)checkSwitchFieldB = new Form.Field.Checkbox("shouldReadNotes","Automatically read a row’s notes",shouldReadNotes)checkSwitchFieldC = new Form.Field.Checkbox("shouldReadOutline","Read entire outline",shouldReadOutline)inputForm = new Form()inputForm.addField(checkSwitchFieldA)inputForm.addField(checkSwitchFieldB)inputForm.addField(checkSwitchFieldC)inputForm.validate = function(formObject){return true}formPrompt = (shouldReadOutline) ? "Read Outline Rows":"Read Selected Rows"spokenPrompt = (shouldReadOutline) ? "Reed Outline Rows":"Reed Selected Rows"buttonTitle = "Continue"utterance = createUtterance(spokenPrompt)synthesizer.speakUtterance(utterance)formObject = await inputForm.show(formPrompt, buttonTitle)shouldIdentifyRow = formObject.values['shouldIdentifyRow']console.log('shouldIdentifyRow', shouldIdentifyRow)preferences.write("shouldIdentifyRow", shouldIdentifyRow)shouldReadNotes = formObject.values['shouldReadNotes']console.log('shouldReadNotes', shouldReadNotes)preferences.write("shouldReadNotes", shouldReadNotes)shouldReadOutline = formObject.values['shouldReadOutline']console.log('shouldReadOutline', shouldReadOutline)preferences.write("shouldReadOutline", shouldReadOutline)var itemsToRead = new Array()if(shouldReadOutline){itemsToRead = rootItem.descendants} else {itemsToRead = selection.items}if(itemsToRead.length === 0){throw {name: "Selection Issue",message: "No items have been selected to be read."}}rowCount = itemsToRead.lengthrowOrRows = (rowCount === 1) ? "row":"rows"var textSegments = new Array()itemsToRead.forEach(item => {if(shouldIdentifyRow){itemID = genPositionID(item)spokenID = itemID.replaceAll('.', ' point ')identifyingPhrase = `Row ${spokenID}`textSegments.push(identifyingPhrase)}rowText = item.topicif(rowText.length === 0){rowText = "Empty row."}textSegments.push(rowText)if(shouldReadNotes){noteText = item.noteif(noteText.length > 0){textSegments.push("Note for row.")textSegments.push(noteText)}}})addedPhrase = (shouldReadNotes) ? "and notes": ""openingUtterance = createUtterance(`Reading ${rowCount} ${rowOrRows} ${addedPhrase}`)openingUtterance.postUtteranceDelay = 0.75var utterances = [openingUtterance]textSegments.forEach(segment => {console.log(segment)utterance = createUtterance(segment)utterance.postUtteranceDelay = 0.5utterances.push(utterance)})utterances.forEach(utterance => {synthesizer.speakUtterance(utterance)})utterance = createUtterance("Done!")synthesizer.speakUtterance(utterance)alertTitle = (shouldReadOutline) ? "Reading Outline Rows":"Reading Selected Rows"alert = new Alert(alertTitle, "Click “Done” button to stop speaking.")alert.addOption("Done")index = await alert.show()synthesizer.stopSpeaking(Speech.Boundary.Word)}catch(err){if(!err.causedByUserCancelling){utterance = createUtterance(err.message)synthesizer.speakUtterance(utterance)new Alert(err.name, err.message).show()}}});action.validate = function(selection, sender){return true};return action;})();