rotor-framework 0.7.6 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +2 -2
- package/package.json +5 -4
- package/src/source/RotorFramework.bs +17 -3
- package/src/source/RotorFrameworkTask.bs +103 -73
- package/src/source/base/BaseReducer.bs +62 -29
- package/src/source/base/BaseViewModel.bs +5 -3
- package/src/source/base/DispatcherOriginal.bs +9 -5
- package/src/source/engine/builder/WidgetCreate.bs +23 -15
- package/src/source/engine/services/Tts.bs +18 -27
- package/src/source/plugins/FocusPlugin.bs +252 -133
- package/src/source/plugins/ObserverPlugin.bs +26 -46
|
@@ -117,7 +117,7 @@ namespace Rotor.ViewBuilder
|
|
|
117
117
|
#if not unittest
|
|
118
118
|
if m.audioGuide = invalid
|
|
119
119
|
#if debug
|
|
120
|
-
? "[TTS_SERVICE][ERROR] Failed to create roAudioGuide instance"
|
|
120
|
+
' ? "[TTS_SERVICE][ERROR] Failed to create roAudioGuide instance"
|
|
121
121
|
#end if
|
|
122
122
|
m.isEnabled = false
|
|
123
123
|
return
|
|
@@ -132,13 +132,13 @@ namespace Rotor.ViewBuilder
|
|
|
132
132
|
m.timerNode.observeFieldScoped("fire", "Rotor_ViewBuilder_ttsDebounceCallback")
|
|
133
133
|
' Note: Timer is NOT started here, only when pending speech is added
|
|
134
134
|
#if debug
|
|
135
|
-
? "[TTS_SERVICE][INFO] Threshold timer created (one-shot, "; m.debounceDelay; "ms)"
|
|
135
|
+
' ? "[TTS_SERVICE][INFO] Threshold timer created (one-shot, "; m.debounceDelay; "ms)"
|
|
136
136
|
#end if
|
|
137
137
|
|
|
138
138
|
' Check device AudioGuide status dynamically
|
|
139
139
|
if not m.getIsDeviceAudioGuideEnabled()
|
|
140
140
|
#if debug
|
|
141
|
-
? "[TTS_SERVICE][INFO] Device AudioGuide is disabled, TTS service disabled"
|
|
141
|
+
' ? "[TTS_SERVICE][INFO] Device AudioGuide is disabled, TTS service disabled"
|
|
142
142
|
#end if
|
|
143
143
|
m.isEnabled = false
|
|
144
144
|
return
|
|
@@ -177,7 +177,7 @@ namespace Rotor.ViewBuilder
|
|
|
177
177
|
if Rotor.Utils.isString(onceKey)
|
|
178
178
|
if m.skipCache.DoesExist(onceKey)
|
|
179
179
|
#if debug
|
|
180
|
-
? "[TTS_SERVICE] Skipping speech with onceKey (already spoken): "; onceKey
|
|
180
|
+
' ? "[TTS_SERVICE] Skipping speech with onceKey (already spoken): "; onceKey
|
|
181
181
|
#end if
|
|
182
182
|
return
|
|
183
183
|
end if
|
|
@@ -197,7 +197,7 @@ namespace Rotor.ViewBuilder
|
|
|
197
197
|
' Check if we should skip duplicate speech
|
|
198
198
|
if dontRepeat and textToSpeak = m.lastSpeech
|
|
199
199
|
#if debug
|
|
200
|
-
? "[TTS_SERVICE] Skipping duplicate speech: "; textToSpeak
|
|
200
|
+
' ? "[TTS_SERVICE] Skipping duplicate speech: "; textToSpeak
|
|
201
201
|
#end if
|
|
202
202
|
return
|
|
203
203
|
end if
|
|
@@ -206,7 +206,7 @@ namespace Rotor.ViewBuilder
|
|
|
206
206
|
' This means: bypass threshold immediately AND set flag to protect from next flush
|
|
207
207
|
if shouldPreventNextFlush
|
|
208
208
|
#if debug
|
|
209
|
-
? "[TTS_SERVICE][OVERRIDE] Current speech bypassing threshold: "; textToSpeak
|
|
209
|
+
' ? "[TTS_SERVICE][OVERRIDE] Current speech bypassing threshold: "; textToSpeak
|
|
210
210
|
#end if
|
|
211
211
|
|
|
212
212
|
' Track if there was pending speech
|
|
@@ -215,7 +215,7 @@ namespace Rotor.ViewBuilder
|
|
|
215
215
|
' IMPORTANT: Execute pending speech FIRST if it exists (maintains correct order)
|
|
216
216
|
if m.pendingSpeech <> invalid
|
|
217
217
|
#if debug
|
|
218
|
-
? "[TTS_SERVICE][OVERRIDE] Executing pending speech first: '"; m.pendingSpeech.textToSpeak; "'"
|
|
218
|
+
' ? "[TTS_SERVICE][OVERRIDE] Executing pending speech first: '"; m.pendingSpeech.textToSpeak; "'"
|
|
219
219
|
#end if
|
|
220
220
|
pendingToExecute = m.pendingSpeech
|
|
221
221
|
m.pendingSpeech = invalid
|
|
@@ -247,7 +247,7 @@ namespace Rotor.ViewBuilder
|
|
|
247
247
|
' This allows rapid menu navigation to filter properly (threshold replaces pending)
|
|
248
248
|
if m.preventNextFlushFlag or m.isPendingProtected
|
|
249
249
|
#if debug
|
|
250
|
-
? "[TTS_SERVICE][OVERRIDE] Flush blocked, speech goes to threshold: "; textToSpeak
|
|
250
|
+
' ? "[TTS_SERVICE][OVERRIDE] Flush blocked, speech goes to threshold: "; textToSpeak
|
|
251
251
|
#end if
|
|
252
252
|
if m.preventNextFlushFlag
|
|
253
253
|
m.preventNextFlushFlag = false ' Clear flag after first use
|
|
@@ -264,15 +264,6 @@ namespace Rotor.ViewBuilder
|
|
|
264
264
|
' Apply threshold to ALL speech (both flush=true and flush=false)
|
|
265
265
|
' This prevents rapid interruptions from focus changes (e.g., "Home Home Home")
|
|
266
266
|
' If new request comes within 300ms, replace pending (filter rapid changes)
|
|
267
|
-
#if debug
|
|
268
|
-
if m.pendingSpeech <> invalid
|
|
269
|
-
? "[TTS_SERVICE][THRESHOLD] Replacing pending: '"; m.pendingSpeech.textToSpeak; "' with: '"; textToSpeak; "'"
|
|
270
|
-
else
|
|
271
|
-
flushLabel = ""
|
|
272
|
-
if shouldFlush then flushLabel = " (will flush)"
|
|
273
|
-
? "[TTS_SERVICE][THRESHOLD] Pending: '"; textToSpeak; "' ("; m.debounceDelay; "ms)"; flushLabel
|
|
274
|
-
end if
|
|
275
|
-
#end if
|
|
276
267
|
m.pendingSpeech = {
|
|
277
268
|
textToSpeak: textToSpeak,
|
|
278
269
|
shouldFlush: shouldFlush,
|
|
@@ -321,7 +312,7 @@ namespace Rotor.ViewBuilder
|
|
|
321
312
|
|
|
322
313
|
' Execute pending speech after threshold passed
|
|
323
314
|
#if debug
|
|
324
|
-
? "[TTS_SERVICE][THRESHOLD] Timer fired, executing: '"; pendingToExecute.textToSpeak; "'"
|
|
315
|
+
' ? "[TTS_SERVICE][THRESHOLD] Timer fired, executing: '"; pendingToExecute.textToSpeak; "'"
|
|
325
316
|
#end if
|
|
326
317
|
|
|
327
318
|
' IMPORTANT: Clear protection flag BEFORE executing pending speech
|
|
@@ -350,7 +341,7 @@ namespace Rotor.ViewBuilder
|
|
|
350
341
|
if isLongText or isMultiSentence
|
|
351
342
|
shouldFlush = true
|
|
352
343
|
#if debug
|
|
353
|
-
? "[TTS_SERVICE] Forcing flush for long/multi-sentence text (len: "; Len(textToSpeak); ", multi: "; isMultiSentence; ")"
|
|
344
|
+
' ? "[TTS_SERVICE] Forcing flush for long/multi-sentence text (len: "; Len(textToSpeak); ", multi: "; isMultiSentence; ")"
|
|
354
345
|
#end if
|
|
355
346
|
end if
|
|
356
347
|
|
|
@@ -372,7 +363,7 @@ namespace Rotor.ViewBuilder
|
|
|
372
363
|
' Handle flush with prevention protection
|
|
373
364
|
if shouldFlush and m.preventNextFlushFlag
|
|
374
365
|
#if debug
|
|
375
|
-
? "[TTS_SERVICE] Flush blocked by preventNextFlush protection"
|
|
366
|
+
' ? "[TTS_SERVICE] Flush blocked by preventNextFlush protection"
|
|
376
367
|
#end if
|
|
377
368
|
shouldFlush = false ' Prevent flush in Say() call too!
|
|
378
369
|
m.preventNextFlushFlag = false
|
|
@@ -391,7 +382,7 @@ namespace Rotor.ViewBuilder
|
|
|
391
382
|
end if
|
|
392
383
|
|
|
393
384
|
#if debug
|
|
394
|
-
? "[TTS_SERVICE] Speaking (ID: "; speechId; "): "; text; " (flush: "; shouldFlush; ", dontRepeat: "; dontRepeat; ")"
|
|
385
|
+
' ? "[TTS_SERVICE] Speaking (ID: "; speechId; "): "; text; " (flush: "; shouldFlush; ", dontRepeat: "; dontRepeat; ")"
|
|
395
386
|
#end if
|
|
396
387
|
|
|
397
388
|
return speechId
|
|
@@ -560,7 +551,7 @@ namespace Rotor.ViewBuilder
|
|
|
560
551
|
end if
|
|
561
552
|
|
|
562
553
|
#if debug
|
|
563
|
-
? "[TTS_SERVICE] Stop speech - flushed all speech and canceled pending"
|
|
554
|
+
' ? "[TTS_SERVICE] Stop speech - flushed all speech and canceled pending"
|
|
564
555
|
#end if
|
|
565
556
|
end sub
|
|
566
557
|
|
|
@@ -585,7 +576,7 @@ namespace Rotor.ViewBuilder
|
|
|
585
576
|
if m.skipCache.DoesExist(key)
|
|
586
577
|
m.skipCache.Delete(key)
|
|
587
578
|
#if debug
|
|
588
|
-
? "[TTS_SERVICE] Removed onceKey from cache: "; key
|
|
579
|
+
' ? "[TTS_SERVICE] Removed onceKey from cache: "; key
|
|
589
580
|
#end if
|
|
590
581
|
end if
|
|
591
582
|
end sub
|
|
@@ -596,7 +587,7 @@ namespace Rotor.ViewBuilder
|
|
|
596
587
|
public sub enable()
|
|
597
588
|
if not m.getIsDeviceAudioGuideEnabled()
|
|
598
589
|
#if debug
|
|
599
|
-
? "[TTS_SERVICE][WARNING] Cannot enable - device AudioGuide is disabled"
|
|
590
|
+
' ? "[TTS_SERVICE][WARNING] Cannot enable - device AudioGuide is disabled"
|
|
600
591
|
#end if
|
|
601
592
|
return
|
|
602
593
|
end if
|
|
@@ -608,7 +599,7 @@ namespace Rotor.ViewBuilder
|
|
|
608
599
|
if rootNode <> invalid and not m.allowNativeAudioGuide
|
|
609
600
|
rootNode.muteAudioGuide = true
|
|
610
601
|
#if debug
|
|
611
|
-
? "[TTS_SERVICE][INFO] Enabled TTS, muted native AudioGuide"
|
|
602
|
+
' ? "[TTS_SERVICE][INFO] Enabled TTS, muted native AudioGuide"
|
|
612
603
|
#end if
|
|
613
604
|
end if
|
|
614
605
|
end sub
|
|
@@ -626,7 +617,7 @@ namespace Rotor.ViewBuilder
|
|
|
626
617
|
if rootNode <> invalid
|
|
627
618
|
rootNode.muteAudioGuide = false
|
|
628
619
|
#if debug
|
|
629
|
-
? "[TTS_SERVICE][INFO] Disabled TTS, unmuted native AudioGuide"
|
|
620
|
+
' ? "[TTS_SERVICE][INFO] Disabled TTS, unmuted native AudioGuide"
|
|
630
621
|
#end if
|
|
631
622
|
end if
|
|
632
623
|
end if
|
|
@@ -638,7 +629,7 @@ namespace Rotor.ViewBuilder
|
|
|
638
629
|
public sub clearOnceCache()
|
|
639
630
|
m.skipCache = {}
|
|
640
631
|
#if debug
|
|
641
|
-
? "[TTS_SERVICE] Once cache cleared"
|
|
632
|
+
' ? "[TTS_SERVICE] Once cache cleared"
|
|
642
633
|
#end if
|
|
643
634
|
end sub
|
|
644
635
|
|