@applicaster/zapp-react-native-utils 15.0.0-alpha.7413430163 → 15.0.0-alpha.7877002324

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.
@@ -72,3 +72,26 @@ export const useAnnouncementActive = (
72
72
 
73
73
  return isActive;
74
74
  };
75
+
76
+ /**
77
+ * Hook to get the current screen reader enabled state
78
+ * Returns a boolean that updates reactively when screen reader is enabled/disabled
79
+ * @returns boolean - true if screen reader is enabled, false otherwise
80
+ */
81
+ export const useScreenReaderEnabled = (
82
+ accessibilityManager: AccessibilityManager
83
+ ) => {
84
+ const [isEnabled, setIsEnabled] = useState(
85
+ accessibilityManager.getState().screenReaderEnabled
86
+ );
87
+
88
+ useEffect(() => {
89
+ const subscription = accessibilityManager
90
+ .getStateAsObservable()
91
+ .subscribe((state) => setIsEnabled(state.screenReaderEnabled));
92
+
93
+ return () => subscription.unsubscribe();
94
+ }, [accessibilityManager]);
95
+
96
+ return isEnabled;
97
+ };
@@ -36,7 +36,20 @@ export class AccessibilityManager {
36
36
  false
37
37
  );
38
38
 
39
- private constructor() {}
39
+ private constructor() {
40
+ this.ttsManager
41
+ .getScreenReaderEnabledAsObservable()
42
+ .subscribe((enabled) => {
43
+ const state = this.state$.getValue();
44
+
45
+ if (state.screenReaderEnabled !== enabled) {
46
+ this.state$.next({
47
+ ...state,
48
+ screenReaderEnabled: enabled,
49
+ });
50
+ }
51
+ });
52
+ }
40
53
 
41
54
  public static getInstance(): AccessibilityManager {
42
55
  if (!AccessibilityManager._instance) {
@@ -92,8 +105,15 @@ export class AccessibilityManager {
92
105
  /**
93
106
  * Adds a heading to the queue, headings will be read before the next text
94
107
  * Each heading will be read once and removed from the queue
108
+ * Does nothing if screen reader is not enabled
95
109
  */
96
110
  public addHeading(heading: string) {
111
+ const state = this.state$.getValue();
112
+
113
+ if (!state.screenReaderEnabled) {
114
+ return;
115
+ }
116
+
97
117
  if (!this.pendingFocusId) {
98
118
  this.pendingFocusId = Date.now().toString();
99
119
  }
@@ -108,6 +128,7 @@ export class AccessibilityManager {
108
128
  *
109
129
  * Implements a delay mechanism to reduce noise during rapid navigation.
110
130
  * Only the most recent announcement will be read after the delay period.
131
+ * Does nothing if screen reader is not enabled
111
132
  */
112
133
  public readText({
113
134
  text,
@@ -116,6 +137,12 @@ export class AccessibilityManager {
116
137
  text: string;
117
138
  keyOfLocalizedText?: string;
118
139
  }) {
140
+ const state = this.state$.getValue();
141
+
142
+ if (!state.screenReaderEnabled) {
143
+ return;
144
+ }
145
+
119
146
  let textToRead = text;
120
147
 
121
148
  if (keyOfLocalizedText) {
@@ -170,7 +170,9 @@ export const getClosedCaptionState = () => {
170
170
  */
171
171
  export class TTSManager {
172
172
  private ttsState$ = new BehaviorSubject<boolean>(false);
173
+ private screenReaderEnabled$ = new BehaviorSubject<boolean>(false);
173
174
  private static ttsManagerInstance: TTSManager;
175
+ private samsungListenerId: number | null = null;
174
176
 
175
177
  private constructor() {
176
178
  this.initialize();
@@ -185,23 +187,84 @@ export class TTSManager {
185
187
  }
186
188
 
187
189
  async initialize() {
188
- if (!isVizioPlatform()) return;
190
+ if (isVizioPlatform()) {
191
+ document.addEventListener(
192
+ "VIZIO_TTS_ENABLED",
193
+ () => {
194
+ log_debug("Vizio screen reader enabled");
195
+ this.screenReaderEnabled$.next(true);
196
+ },
197
+ false
198
+ );
189
199
 
190
- document.addEventListener(
191
- "VIZIO_TTS_ENABLED",
192
- () => {
193
- this.ttsState$.next(true);
194
- },
195
- false
196
- );
200
+ document.addEventListener(
201
+ "VIZIO_TTS_DISABLED",
202
+ () => {
203
+ log_debug("Vizio screen reader disabled");
204
+ this.screenReaderEnabled$.next(false);
205
+ },
206
+ false
207
+ );
208
+ }
197
209
 
198
- document.addEventListener(
199
- "VIZIO_TTS_DISABLED",
200
- () => {
201
- this.ttsState$.next(false);
202
- },
203
- false
204
- );
210
+ if (isLgPlatform() && window.webOS?.service) {
211
+ try {
212
+ //https://webostv.developer.lge.com/develop/references/settings-service
213
+ window.webOS.service.request("luna://com.webos.settingsservice", {
214
+ method: "getSystemSettings",
215
+ parameters: {
216
+ category: "option",
217
+ keys: ["audioGuidance"],
218
+ subscribe: true, // Request a subscription to changes
219
+ },
220
+ onSuccess: (response: any) => {
221
+ const isEnabled = response?.settings?.audioGuidance === "on";
222
+
223
+ log_debug("LG Audio Guidance status changed", {
224
+ isEnabled,
225
+ response,
226
+ });
227
+
228
+ this.screenReaderEnabled$.next(isEnabled);
229
+ },
230
+ onFailure: (error: any) => {
231
+ log_debug("webOS settings subscription failed", { error });
232
+ this.screenReaderEnabled$.next(false);
233
+ },
234
+ });
235
+ } catch (error) {
236
+ log_debug("webOS settings service request error", { error });
237
+ this.screenReaderEnabled$.next(false);
238
+ }
239
+ }
240
+
241
+ if (isSamsungPlatform() && typeof window.tizen !== "undefined") {
242
+ try {
243
+ if (
244
+ window.tizen.accessibility &&
245
+ typeof window.tizen.accessibility
246
+ .addVoiceGuideStatusChangeListener === "function"
247
+ ) {
248
+ this.samsungListenerId =
249
+ window.tizen.accessibility.addVoiceGuideStatusChangeListener(
250
+ (enabled: boolean) => {
251
+ log_debug("Samsung Voice Guide status changed", { enabled });
252
+ this.screenReaderEnabled$.next(!!enabled);
253
+ }
254
+ );
255
+
256
+ log_debug("Samsung Voice Guide listener registered", {
257
+ listenerId: this.samsungListenerId,
258
+ });
259
+ } else {
260
+ log_debug("Samsung accessibility API not available");
261
+ this.screenReaderEnabled$.next(false);
262
+ }
263
+ } catch (error) {
264
+ log_debug("Samsung Voice Guide listener error", { error });
265
+ this.screenReaderEnabled$.next(false);
266
+ }
267
+ }
205
268
  }
206
269
 
207
270
  getCurrentState(): boolean {
@@ -212,17 +275,38 @@ export class TTSManager {
212
275
  return this.ttsState$.asObservable();
213
276
  }
214
277
 
278
+ getScreenReaderEnabledAsObservable() {
279
+ return this.screenReaderEnabled$.asObservable();
280
+ }
281
+
215
282
  readText(text: string) {
216
283
  this.ttsState$.next(true);
217
284
 
218
- if (isSamsungPlatform() && window.speechSynthesis) {
219
- const utterance = new SpeechSynthesisUtterance(text);
285
+ if (
286
+ isSamsungPlatform() &&
287
+ typeof window.tizen !== "undefined" &&
288
+ window.tizen.speech
289
+ ) {
290
+ try {
291
+ const successCallback = () => {
292
+ log_debug("Samsung TTS play started successfully");
293
+ // Estimate reading time and set inactive when done
294
+ this.scheduleTTSComplete(text);
295
+ };
220
296
 
221
- window.speechSynthesis.cancel(); // Cancel previous speech before speaking new text
222
- window.speechSynthesis.speak(utterance);
297
+ const errorCallback = (error: any) => {
298
+ log_debug("Samsung TTS error", { error: error?.message || error });
299
+ this.ttsState$.next(false);
300
+ };
223
301
 
224
- // Estimate reading time and set inactive when done
225
- this.scheduleTTSComplete(text);
302
+ // Clear any previous speech before speaking new text
303
+ window.tizen.speech.stop();
304
+
305
+ window.tizen.speech.speak(text, successCallback, errorCallback);
306
+ } catch (error) {
307
+ log_debug("Samsung TTS speak() error", { error });
308
+ this.ttsState$.next(false);
309
+ }
226
310
  }
227
311
 
228
312
  if (isLgPlatform() && window.webOS?.service) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applicaster/zapp-react-native-utils",
3
- "version": "15.0.0-alpha.7413430163",
3
+ "version": "15.0.0-alpha.7877002324",
4
4
  "description": "Applicaster Zapp React Native utilities package",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -27,7 +27,7 @@
27
27
  },
28
28
  "homepage": "https://github.com/applicaster/quickbrick#readme",
29
29
  "dependencies": {
30
- "@applicaster/applicaster-types": "15.0.0-alpha.7413430163",
30
+ "@applicaster/applicaster-types": "15.0.0-alpha.7877002324",
31
31
  "buffer": "^5.2.1",
32
32
  "camelize": "^1.0.0",
33
33
  "dayjs": "^1.11.10",