!7 sclass FakeFake > DynModule { transient JTextArea ta; S text; LS log = synchroList(); transient WaitForStableValue wait = new(2.0); transient S preloading; start { onSpeechRecognized(voidfunc(fS s) { if (ai_isStandardCommand(s)) ret; log("Heard: " + s); trigger(); }); doEvery(1000, r { wait.set(trim(firstLine(text))); S s = wait.get(); if (nempty(s)) dm_callOpt(dm_voiceOutputModule(), 'preload, s); }); } void trigger { swing { if (!dm_visible() || ta == null) ret; fS line = trim(firstLine(text)); if (empty(line)) ret; log("Said: " + line); setText(ta, dropFirstLine(text)); // TODO: move cursor thread { dm_say(line); } } } void log(S s) { log.add(print(s)); persistMe(); } visualize { ta = jLiveValueWordWrapTypeWriterTextArea_bothWays(dm_fieldLiveValue('text)); onCtrlEnter(ta, r trigger); ret ta; } }