aboutsummaryrefslogtreecommitdiff
path: root/src/client/util/DictationManager.ts
diff options
context:
space:
mode:
authorSam Wilkins <samwilkins333@gmail.com>2019-07-30 20:19:58 -0400
committerSam Wilkins <samwilkins333@gmail.com>2019-07-30 20:19:58 -0400
commite0316c21838613df0fbf43df6a9ca5d696c52f47 (patch)
tree634c400ab3a5ee7d7cf2d6e9b3be026081ae05c2 /src/client/util/DictationManager.ts
parent1aac1e8820c62a5f06d7e7630394e0bd58b19a94 (diff)
more interesting speech commands and command manager pattern for DictationManager
Diffstat (limited to 'src/client/util/DictationManager.ts')
-rw-r--r--src/client/util/DictationManager.ts88
1 files changed, 88 insertions, 0 deletions
diff --git a/src/client/util/DictationManager.ts b/src/client/util/DictationManager.ts
index b58bdb6c7..60b25afc5 100644
--- a/src/client/util/DictationManager.ts
+++ b/src/client/util/DictationManager.ts
@@ -1,3 +1,10 @@
+import { string } from "prop-types";
+import { observable, action } from "mobx";
+import { SelectionManager } from "./SelectionManager";
+import { DocumentView } from "../views/nodes/DocumentView";
+import { UndoManager } from "./UndoManager";
+import * as converter from "words-to-numbers";
+
namespace CORE {
export interface IWindow extends Window {
webkitSpeechRecognition: any;
@@ -5,9 +12,14 @@ namespace CORE {
}
const { webkitSpeechRecognition }: CORE.IWindow = window as CORE.IWindow;
+export type Action = (target: DocumentView) => any | Promise<any>;
+export type DynamicAction = (target: DocumentView, matches: RegExpExecArray) => any | Promise<any>;
+export type RegexEntry = { key: RegExp, value: DynamicAction };
export default class DictationManager {
public static Instance = new DictationManager();
+ private registeredCommands = new Map<string, Action>();
+ private registeredRegexes: RegexEntry[] = [];
private isListening = false;
private recognizer: any;
@@ -17,8 +29,16 @@ export default class DictationManager {
this.recognizer.continuous = true;
}
+ @observable public current = "";
+
+ @action
finish = (handler: any, data: any) => {
+ this.current = data;
handler(data);
+ this.stop();
+ }
+
+ stop = () => {
this.isListening = false;
this.recognizer.stop();
}
@@ -36,4 +56,72 @@ export default class DictationManager {
}
+ private sanitize = (title: string) => {
+ return title.replace("...", "").toLowerCase().trim();
+ }
+
+ public registerStatic = (keys: Array<string>, action: Action, overwrite = false) => {
+ let success = true;
+ keys.forEach(key => {
+ key = this.sanitize(key);
+ let existing = this.registeredCommands.get(key);
+ if (!existing || overwrite) {
+ this.registeredCommands.set(key, action);
+ } else {
+ success = false;
+ }
+ });
+ return success;
+ }
+
+ public interpretNumber = (number: string) => {
+ let initial = parseInt(number);
+ if (!isNaN(initial)) {
+ return initial;
+ }
+ let converted = converter.wordsToNumbers(number, { fuzzy: true });
+ if (converted === null) {
+ return NaN;
+ }
+ return typeof converted === "string" ? parseInt(converted) : converted;
+ }
+
+ public registerDynamic = (dynamicKey: RegExp, action: DynamicAction) => {
+ this.registeredRegexes.push({
+ key: dynamicKey,
+ value: action
+ });
+ }
+
+ public execute = async (phrase: string) => {
+ let target = SelectionManager.SelectedDocuments()[0];
+ if (!target) {
+ return;
+ }
+ let batch = UndoManager.StartBatch("Dictation Action");
+ phrase = this.sanitize(phrase);
+
+ let registeredAction = this.registeredCommands.get(phrase);
+ if (registeredAction) {
+ await registeredAction(target);
+ return true;
+ }
+
+ let success = false;
+ for (let entry of this.registeredRegexes) {
+ let regex = entry.key;
+ let registeredDynamicAction = entry.value;
+ let matches = regex.exec(phrase);
+ regex.lastIndex = 0;
+ if (matches !== null) {
+ await registeredDynamicAction(target, matches);
+ success = true;
+ break;
+ }
+ }
+ batch.end();
+
+ return success;
+ }
+
} \ No newline at end of file