@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 (
|
|
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
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
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
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
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 (
|
|
219
|
-
|
|
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
|
-
|
|
222
|
-
|
|
297
|
+
const errorCallback = (error: any) => {
|
|
298
|
+
log_debug("Samsung TTS error", { error: error?.message || error });
|
|
299
|
+
this.ttsState$.next(false);
|
|
300
|
+
};
|
|
223
301
|
|
|
224
|
-
|
|
225
|
-
|
|
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.
|
|
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.
|
|
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",
|