@angular-helpers/browser-web-apis 21.4.0 → 21.5.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/README.es.md +68 -4
- package/README.md +64 -5
- package/fesm2022/angular-helpers-browser-web-apis.mjs +377 -333
- package/package.json +2 -2
- package/types/angular-helpers-browser-web-apis.d.ts +132 -100
|
@@ -1,33 +1,22 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import {
|
|
2
|
+
import { InjectionToken, inject, DestroyRef, PLATFORM_ID, Injectable, signal, computed, isSignal, effect, ElementRef, makeEnvironmentProviders } from '@angular/core';
|
|
3
3
|
import { isPlatformBrowser, isPlatformServer } from '@angular/common';
|
|
4
|
-
import { Observable, fromEvent, Subject, of, map as map$1 } from 'rxjs';
|
|
4
|
+
import { Observable, fromEvent, BehaviorSubject, Subject, of, map as map$1 } from 'rxjs';
|
|
5
5
|
import { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';
|
|
6
6
|
import { filter, distinctUntilChanged, map } from 'rxjs/operators';
|
|
7
7
|
import { Router } from '@angular/router';
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
isSupported() {
|
|
23
|
-
return typeof navigator !== 'undefined' && 'permissions' in navigator;
|
|
24
|
-
}
|
|
25
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: PermissionsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
26
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: PermissionsService });
|
|
27
|
-
}
|
|
28
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: PermissionsService, decorators: [{
|
|
29
|
-
type: Injectable
|
|
30
|
-
}] });
|
|
9
|
+
const BROWSER_API_LOGGER = new InjectionToken('BROWSER_API_LOGGER', {
|
|
10
|
+
providedIn: 'root',
|
|
11
|
+
factory: () => ({
|
|
12
|
+
// oxlint-disable-next-line no-console
|
|
13
|
+
info: (message) => console.info(message),
|
|
14
|
+
// oxlint-disable-next-line no-console
|
|
15
|
+
warn: (message) => console.warn(message),
|
|
16
|
+
// oxlint-disable-next-line no-console
|
|
17
|
+
error: (message, error) => console.error(message, error),
|
|
18
|
+
}),
|
|
19
|
+
});
|
|
31
20
|
|
|
32
21
|
/**
|
|
33
22
|
* Base class for all Browser Web API services.
|
|
@@ -35,7 +24,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
|
|
|
35
24
|
* - Platform detection (browser vs server)
|
|
36
25
|
* - Support assertion via Template Method
|
|
37
26
|
* - Error creation with cause chaining
|
|
38
|
-
* - Structured logging
|
|
27
|
+
* - Structured logging via injectable BROWSER_API_LOGGER token
|
|
39
28
|
* - Lifecycle management with destroyRef
|
|
40
29
|
*
|
|
41
30
|
* Services that also need permission querying should extend
|
|
@@ -44,6 +33,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
|
|
|
44
33
|
class BrowserApiBaseService {
|
|
45
34
|
destroyRef = inject(DestroyRef);
|
|
46
35
|
platformId = inject(PLATFORM_ID);
|
|
36
|
+
logger = inject(BROWSER_API_LOGGER);
|
|
47
37
|
/**
|
|
48
38
|
* Check if running in browser environment using Angular's platform detection.
|
|
49
39
|
*/
|
|
@@ -57,8 +47,8 @@ class BrowserApiBaseService {
|
|
|
57
47
|
return isPlatformServer(this.platformId);
|
|
58
48
|
}
|
|
59
49
|
/**
|
|
60
|
-
* Template Method:
|
|
61
|
-
*
|
|
50
|
+
* Template Method: asserts the service can run in the current environment.
|
|
51
|
+
* Subclasses must call super.ensureSupported() and then add their own API check.
|
|
62
52
|
*/
|
|
63
53
|
ensureSupported() {
|
|
64
54
|
if (!this.isBrowserEnvironment()) {
|
|
@@ -76,16 +66,22 @@ class BrowserApiBaseService {
|
|
|
76
66
|
return error;
|
|
77
67
|
}
|
|
78
68
|
/**
|
|
79
|
-
* Log an error
|
|
69
|
+
* Log an error through the injected BROWSER_API_LOGGER (default: console).
|
|
80
70
|
*/
|
|
81
71
|
logError(message, error) {
|
|
82
|
-
|
|
72
|
+
this.logger.error(`[${this.getApiName()}] ${message}`, error);
|
|
83
73
|
}
|
|
84
74
|
/**
|
|
85
|
-
* Log
|
|
75
|
+
* Log a warning through the injected BROWSER_API_LOGGER (default: console).
|
|
76
|
+
*/
|
|
77
|
+
logWarn(message) {
|
|
78
|
+
this.logger.warn(`[${this.getApiName()}] ${message}`);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Log an informational message through the injected BROWSER_API_LOGGER (default: console).
|
|
86
82
|
*/
|
|
87
83
|
logInfo(message) {
|
|
88
|
-
|
|
84
|
+
this.logger.info(`[${this.getApiName()}] ${message}`);
|
|
89
85
|
}
|
|
90
86
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: BrowserApiBaseService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
91
87
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: BrowserApiBaseService });
|
|
@@ -94,59 +90,54 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
|
|
|
94
90
|
type: Injectable
|
|
95
91
|
}] });
|
|
96
92
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
*/
|
|
105
|
-
class PermissionAwareBrowserApiBaseService extends BrowserApiBaseService {
|
|
106
|
-
permissionsService = inject(PermissionsService);
|
|
107
|
-
/**
|
|
108
|
-
* Query the Permissions API for the given permission name.
|
|
109
|
-
* Returns `true` if the permission state is `'granted'`.
|
|
110
|
-
*/
|
|
111
|
-
async requestPermission(permission) {
|
|
112
|
-
if (this.isServerEnvironment()) {
|
|
113
|
-
throw new Error(`${this.getApiName()} API not available in server environment`);
|
|
93
|
+
class PermissionsService extends BrowserApiBaseService {
|
|
94
|
+
getApiName() {
|
|
95
|
+
return 'permissions';
|
|
96
|
+
}
|
|
97
|
+
async query(descriptor) {
|
|
98
|
+
if (!this.isSupported()) {
|
|
99
|
+
throw new Error('Permissions API not supported in this environment');
|
|
114
100
|
}
|
|
115
101
|
try {
|
|
116
|
-
|
|
117
|
-
return status.state === 'granted';
|
|
102
|
+
return await navigator.permissions.query(descriptor);
|
|
118
103
|
}
|
|
119
104
|
catch (error) {
|
|
120
|
-
|
|
121
|
-
|
|
105
|
+
// Firefox does not support querying 'camera', 'microphone', or 'speaker' via
|
|
106
|
+
// the Permissions API and throws a TypeError. Return a synthetic 'prompt' status
|
|
107
|
+
// so callers fall through to the native getUserMedia / requestPermission flow.
|
|
108
|
+
if (error instanceof TypeError) {
|
|
109
|
+
return { state: 'prompt', onchange: null };
|
|
110
|
+
}
|
|
111
|
+
this.logError(`Error querying permission for ${descriptor.name}:`, error);
|
|
112
|
+
throw error;
|
|
122
113
|
}
|
|
123
114
|
}
|
|
124
|
-
|
|
125
|
-
|
|
115
|
+
isSupported() {
|
|
116
|
+
return this.isBrowserEnvironment() && 'permissions' in navigator;
|
|
117
|
+
}
|
|
118
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: PermissionsService, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
119
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: PermissionsService });
|
|
126
120
|
}
|
|
127
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type:
|
|
121
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: PermissionsService, decorators: [{
|
|
128
122
|
type: Injectable
|
|
129
123
|
}] });
|
|
130
124
|
|
|
131
|
-
class CameraService extends
|
|
125
|
+
class CameraService extends BrowserApiBaseService {
|
|
132
126
|
currentStream = null;
|
|
133
127
|
getApiName() {
|
|
134
128
|
return 'camera';
|
|
135
129
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
130
|
+
ensureSupported() {
|
|
131
|
+
super.ensureSupported();
|
|
132
|
+
if (!navigator.mediaDevices?.getUserMedia) {
|
|
133
|
+
throw new Error('Camera API not supported — a secure context (HTTPS) is required');
|
|
139
134
|
}
|
|
140
135
|
}
|
|
141
136
|
async startCamera(constraints) {
|
|
142
|
-
this.
|
|
137
|
+
this.ensureSupported();
|
|
143
138
|
if (this.currentStream) {
|
|
144
139
|
this.stopCamera();
|
|
145
140
|
}
|
|
146
|
-
const permissionStatus = await this.permissionsService.query({ name: 'camera' });
|
|
147
|
-
if (permissionStatus.state !== 'granted') {
|
|
148
|
-
throw new Error('Camera permission required. Please grant camera access and try again.');
|
|
149
|
-
}
|
|
150
141
|
try {
|
|
151
142
|
const streamConstraints = constraints || {
|
|
152
143
|
video: {
|
|
@@ -159,7 +150,7 @@ class CameraService extends PermissionAwareBrowserApiBaseService {
|
|
|
159
150
|
return this.currentStream;
|
|
160
151
|
}
|
|
161
152
|
catch (error) {
|
|
162
|
-
|
|
153
|
+
this.logError('Error starting camera:', error);
|
|
163
154
|
if (error instanceof Error && error.name === 'NotAllowedError') {
|
|
164
155
|
throw this.createError('Camera permission denied by user. Please allow camera access in your browser settings and refresh the page.', error);
|
|
165
156
|
}
|
|
@@ -201,19 +192,24 @@ class CameraService extends PermissionAwareBrowserApiBaseService {
|
|
|
201
192
|
return this.startCamera(finalConstraints);
|
|
202
193
|
}
|
|
203
194
|
async getCameraCapabilities(deviceId) {
|
|
204
|
-
this.
|
|
195
|
+
this.ensureSupported();
|
|
205
196
|
try {
|
|
197
|
+
const activeTrack = this.currentStream
|
|
198
|
+
?.getVideoTracks()
|
|
199
|
+
.find((t) => t.getSettings().deviceId === deviceId);
|
|
200
|
+
if (activeTrack) {
|
|
201
|
+
return activeTrack.getCapabilities() ?? null;
|
|
202
|
+
}
|
|
206
203
|
const stream = await navigator.mediaDevices.getUserMedia({
|
|
207
204
|
video: { deviceId: { exact: deviceId } },
|
|
208
205
|
});
|
|
209
206
|
const videoTrack = stream.getVideoTracks()[0];
|
|
210
207
|
const capabilities = videoTrack.getCapabilities();
|
|
211
|
-
// Clean up the stream
|
|
212
208
|
stream.getTracks().forEach((track) => track.stop());
|
|
213
|
-
return capabilities
|
|
209
|
+
return capabilities ?? null;
|
|
214
210
|
}
|
|
215
211
|
catch (error) {
|
|
216
|
-
|
|
212
|
+
this.logError('Error getting camera capabilities:', error);
|
|
217
213
|
return null;
|
|
218
214
|
}
|
|
219
215
|
}
|
|
@@ -224,19 +220,19 @@ class CameraService extends PermissionAwareBrowserApiBaseService {
|
|
|
224
220
|
return this.currentStream !== null;
|
|
225
221
|
}
|
|
226
222
|
async getVideoInputDevices() {
|
|
227
|
-
this.
|
|
223
|
+
this.ensureSupported();
|
|
228
224
|
try {
|
|
229
225
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
230
226
|
return devices.filter((device) => device.kind === 'videoinput');
|
|
231
227
|
}
|
|
232
228
|
catch (error) {
|
|
233
|
-
|
|
229
|
+
this.logError('Error enumerating video devices:', error);
|
|
234
230
|
throw this.createError('Failed to enumerate video devices', error);
|
|
235
231
|
}
|
|
236
232
|
}
|
|
237
233
|
// Direct access to native camera API
|
|
238
234
|
getNativeMediaDevices() {
|
|
239
|
-
this.
|
|
235
|
+
this.ensureSupported();
|
|
240
236
|
return navigator.mediaDevices;
|
|
241
237
|
}
|
|
242
238
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: CameraService, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
@@ -250,13 +246,14 @@ class GeolocationService extends BrowserApiBaseService {
|
|
|
250
246
|
getApiName() {
|
|
251
247
|
return 'geolocation';
|
|
252
248
|
}
|
|
253
|
-
|
|
249
|
+
ensureSupported() {
|
|
250
|
+
super.ensureSupported();
|
|
254
251
|
if (!('geolocation' in navigator)) {
|
|
255
|
-
throw new Error('Geolocation API not supported
|
|
252
|
+
throw new Error('Geolocation API not supported — a secure context (HTTPS) is required');
|
|
256
253
|
}
|
|
257
254
|
}
|
|
258
255
|
getCurrentPosition(options) {
|
|
259
|
-
this.
|
|
256
|
+
this.ensureSupported();
|
|
260
257
|
return new Promise((resolve, reject) => {
|
|
261
258
|
navigator.geolocation.getCurrentPosition((position) => resolve(position), (error) => {
|
|
262
259
|
this.logError('Error getting position:', error);
|
|
@@ -265,7 +262,7 @@ class GeolocationService extends BrowserApiBaseService {
|
|
|
265
262
|
});
|
|
266
263
|
}
|
|
267
264
|
watchPosition(options) {
|
|
268
|
-
this.
|
|
265
|
+
this.ensureSupported();
|
|
269
266
|
return new Observable((observer) => {
|
|
270
267
|
const watchId = navigator.geolocation.watchPosition((position) => observer.next(position), (error) => {
|
|
271
268
|
this.logError('Error watching position:', error);
|
|
@@ -281,7 +278,7 @@ class GeolocationService extends BrowserApiBaseService {
|
|
|
281
278
|
}
|
|
282
279
|
// Direct access to native geolocation API
|
|
283
280
|
getNativeGeolocation() {
|
|
284
|
-
this.
|
|
281
|
+
this.ensureSupported();
|
|
285
282
|
return navigator.geolocation;
|
|
286
283
|
}
|
|
287
284
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: GeolocationService, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
@@ -295,24 +292,25 @@ class MediaDevicesService extends BrowserApiBaseService {
|
|
|
295
292
|
getApiName() {
|
|
296
293
|
return 'media-devices';
|
|
297
294
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
295
|
+
ensureSupported() {
|
|
296
|
+
super.ensureSupported();
|
|
297
|
+
if (!navigator.mediaDevices) {
|
|
298
|
+
throw new Error('MediaDevices API not supported — a secure context (HTTPS) is required');
|
|
301
299
|
}
|
|
302
300
|
}
|
|
303
301
|
async getDevices() {
|
|
304
|
-
this.
|
|
302
|
+
this.ensureSupported();
|
|
305
303
|
try {
|
|
306
304
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
307
305
|
return devices;
|
|
308
306
|
}
|
|
309
307
|
catch (error) {
|
|
310
|
-
|
|
308
|
+
this.logError('Error enumerating devices:', error);
|
|
311
309
|
throw this.createError('Failed to enumerate media devices', error);
|
|
312
310
|
}
|
|
313
311
|
}
|
|
314
312
|
async getUserMedia(constraints) {
|
|
315
|
-
this.
|
|
313
|
+
this.ensureSupported();
|
|
316
314
|
try {
|
|
317
315
|
const defaultConstraints = {
|
|
318
316
|
video: true,
|
|
@@ -322,12 +320,12 @@ class MediaDevicesService extends BrowserApiBaseService {
|
|
|
322
320
|
return await navigator.mediaDevices.getUserMedia(finalConstraints);
|
|
323
321
|
}
|
|
324
322
|
catch (error) {
|
|
325
|
-
|
|
323
|
+
this.logError('Error getting user media:', error);
|
|
326
324
|
throw this.handleMediaError(error);
|
|
327
325
|
}
|
|
328
326
|
}
|
|
329
327
|
async getDisplayMedia(constraints) {
|
|
330
|
-
this.
|
|
328
|
+
this.ensureSupported();
|
|
331
329
|
if (!('getDisplayMedia' in navigator.mediaDevices)) {
|
|
332
330
|
throw new Error('Display media API not supported in this browser');
|
|
333
331
|
}
|
|
@@ -340,12 +338,12 @@ class MediaDevicesService extends BrowserApiBaseService {
|
|
|
340
338
|
return await navigator.mediaDevices.getDisplayMedia(finalConstraints);
|
|
341
339
|
}
|
|
342
340
|
catch (error) {
|
|
343
|
-
|
|
341
|
+
this.logError('Error getting display media:', error);
|
|
344
342
|
throw this.createError('Failed to get display media', error);
|
|
345
343
|
}
|
|
346
344
|
}
|
|
347
345
|
watchDeviceChanges() {
|
|
348
|
-
this.
|
|
346
|
+
this.ensureSupported();
|
|
349
347
|
return new Observable((observer) => {
|
|
350
348
|
const handleDeviceChange = async () => {
|
|
351
349
|
try {
|
|
@@ -353,7 +351,7 @@ class MediaDevicesService extends BrowserApiBaseService {
|
|
|
353
351
|
observer.next(devices);
|
|
354
352
|
}
|
|
355
353
|
catch (error) {
|
|
356
|
-
|
|
354
|
+
this.logError('Error handling device change:', error);
|
|
357
355
|
}
|
|
358
356
|
};
|
|
359
357
|
// Listen for device changes
|
|
@@ -408,7 +406,7 @@ class MediaDevicesService extends BrowserApiBaseService {
|
|
|
408
406
|
}
|
|
409
407
|
// Direct access to native media devices API
|
|
410
408
|
getNativeMediaDevices() {
|
|
411
|
-
this.
|
|
409
|
+
this.ensureSupported();
|
|
412
410
|
return navigator.mediaDevices;
|
|
413
411
|
}
|
|
414
412
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MediaDevicesService, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
@@ -422,22 +420,24 @@ class NotificationService extends BrowserApiBaseService {
|
|
|
422
420
|
getApiName() {
|
|
423
421
|
return 'notifications';
|
|
424
422
|
}
|
|
423
|
+
ensureSupported() {
|
|
424
|
+
super.ensureSupported();
|
|
425
|
+
if (!('Notification' in window)) {
|
|
426
|
+
throw new Error('Notifications API not supported in this browser');
|
|
427
|
+
}
|
|
428
|
+
}
|
|
425
429
|
get permission() {
|
|
430
|
+
if (!this.isBrowserEnvironment() || !('Notification' in window)) {
|
|
431
|
+
return 'default';
|
|
432
|
+
}
|
|
426
433
|
return Notification.permission;
|
|
427
434
|
}
|
|
428
|
-
isSupported() {
|
|
429
|
-
return this.isBrowserEnvironment() && 'Notification' in window;
|
|
430
|
-
}
|
|
431
435
|
async requestNotificationPermission() {
|
|
432
|
-
|
|
433
|
-
throw new Error('Notification API not supported in this browser');
|
|
434
|
-
}
|
|
436
|
+
this.ensureSupported();
|
|
435
437
|
return Notification.requestPermission();
|
|
436
438
|
}
|
|
437
439
|
async showNotification(title, options) {
|
|
438
|
-
|
|
439
|
-
throw new Error('Notification API not supported in this browser');
|
|
440
|
-
}
|
|
440
|
+
this.ensureSupported();
|
|
441
441
|
if (Notification.permission !== 'granted') {
|
|
442
442
|
throw new Error('Notification permission required. Please grant notification access and try again.');
|
|
443
443
|
}
|
|
@@ -456,38 +456,33 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
|
|
|
456
456
|
type: Injectable
|
|
457
457
|
}] });
|
|
458
458
|
|
|
459
|
-
class ClipboardService extends
|
|
459
|
+
class ClipboardService extends BrowserApiBaseService {
|
|
460
460
|
getApiName() {
|
|
461
461
|
return 'clipboard';
|
|
462
462
|
}
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
const permissionStatus = await this.permissionsService.query({
|
|
468
|
-
name: `clipboard-${action}`,
|
|
469
|
-
});
|
|
470
|
-
if (permissionStatus.state !== 'granted') {
|
|
471
|
-
throw new Error(`Clipboard ${action} permission required. Please grant clipboard access and try again.`);
|
|
463
|
+
ensureSupported() {
|
|
464
|
+
super.ensureSupported();
|
|
465
|
+
if (!navigator.clipboard) {
|
|
466
|
+
throw new Error('Clipboard API not supported \u2014 a secure context (HTTPS) is required');
|
|
472
467
|
}
|
|
473
468
|
}
|
|
474
469
|
async writeText(text) {
|
|
475
|
-
|
|
470
|
+
this.ensureSupported();
|
|
476
471
|
try {
|
|
477
472
|
await navigator.clipboard.writeText(text);
|
|
478
473
|
}
|
|
479
474
|
catch (error) {
|
|
480
|
-
|
|
475
|
+
this.logError('Error writing to clipboard:', error);
|
|
481
476
|
throw error;
|
|
482
477
|
}
|
|
483
478
|
}
|
|
484
479
|
async readText() {
|
|
485
|
-
|
|
480
|
+
this.ensureSupported();
|
|
486
481
|
try {
|
|
487
482
|
return await navigator.clipboard.readText();
|
|
488
483
|
}
|
|
489
484
|
catch (error) {
|
|
490
|
-
|
|
485
|
+
this.logError('Error reading from clipboard:', error);
|
|
491
486
|
throw error;
|
|
492
487
|
}
|
|
493
488
|
}
|
|
@@ -659,14 +654,15 @@ class BatteryService extends BrowserApiBaseService {
|
|
|
659
654
|
getApiName() {
|
|
660
655
|
return 'battery';
|
|
661
656
|
}
|
|
662
|
-
|
|
657
|
+
ensureSupported() {
|
|
658
|
+
super.ensureSupported();
|
|
663
659
|
const nav = navigator;
|
|
664
660
|
if (!('getBattery' in nav)) {
|
|
665
|
-
throw new Error('Battery API not supported in this browser');
|
|
661
|
+
throw new Error('Battery Status API not supported in this browser');
|
|
666
662
|
}
|
|
667
663
|
}
|
|
668
664
|
async initialize() {
|
|
669
|
-
this.
|
|
665
|
+
this.ensureSupported();
|
|
670
666
|
try {
|
|
671
667
|
const nav = navigator;
|
|
672
668
|
this.batteryManager = await nav.getBattery();
|
|
@@ -674,7 +670,7 @@ class BatteryService extends BrowserApiBaseService {
|
|
|
674
670
|
return batteryInfo;
|
|
675
671
|
}
|
|
676
672
|
catch (error) {
|
|
677
|
-
|
|
673
|
+
this.logError('Error initializing battery API:', error);
|
|
678
674
|
throw this.createError('Failed to initialize battery API', error);
|
|
679
675
|
}
|
|
680
676
|
}
|
|
@@ -743,19 +739,20 @@ class WebShareService extends BrowserApiBaseService {
|
|
|
743
739
|
getApiName() {
|
|
744
740
|
return 'web-share';
|
|
745
741
|
}
|
|
746
|
-
|
|
742
|
+
ensureSupported() {
|
|
743
|
+
super.ensureSupported();
|
|
747
744
|
if (!('share' in navigator)) {
|
|
748
745
|
throw new Error('Web Share API not supported in this browser');
|
|
749
746
|
}
|
|
750
747
|
}
|
|
751
748
|
async share(data) {
|
|
752
|
-
this.
|
|
749
|
+
this.ensureSupported();
|
|
753
750
|
try {
|
|
754
751
|
await navigator.share(data);
|
|
755
752
|
return { shared: true };
|
|
756
753
|
}
|
|
757
754
|
catch (error) {
|
|
758
|
-
|
|
755
|
+
this.logError('Error sharing:', error);
|
|
759
756
|
const errorMessage = error instanceof Error ? error.message : 'Share failed';
|
|
760
757
|
return { shared: false, error: errorMessage };
|
|
761
758
|
}
|
|
@@ -772,7 +769,7 @@ class WebShareService extends BrowserApiBaseService {
|
|
|
772
769
|
}
|
|
773
770
|
// Direct access to native share API
|
|
774
771
|
getNativeShare() {
|
|
775
|
-
this.
|
|
772
|
+
this.ensureSupported();
|
|
776
773
|
return navigator.share;
|
|
777
774
|
}
|
|
778
775
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: WebShareService, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
@@ -784,7 +781,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
|
|
|
784
781
|
|
|
785
782
|
class WebStorageService extends BrowserApiBaseService {
|
|
786
783
|
storageEvents = signal(null, ...(ngDevMode ? [{ debugName: "storageEvents" }] : /* istanbul ignore next */ []));
|
|
787
|
-
destroyRef = inject(DestroyRef);
|
|
788
784
|
constructor() {
|
|
789
785
|
super();
|
|
790
786
|
this.setupEventListeners();
|
|
@@ -792,8 +788,9 @@ class WebStorageService extends BrowserApiBaseService {
|
|
|
792
788
|
getApiName() {
|
|
793
789
|
return 'storage';
|
|
794
790
|
}
|
|
795
|
-
|
|
796
|
-
|
|
791
|
+
ensureSupported() {
|
|
792
|
+
super.ensureSupported();
|
|
793
|
+
if (typeof Storage === 'undefined') {
|
|
797
794
|
throw new Error('Storage API not supported in this browser');
|
|
798
795
|
}
|
|
799
796
|
}
|
|
@@ -803,14 +800,13 @@ class WebStorageService extends BrowserApiBaseService {
|
|
|
803
800
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
804
801
|
.subscribe((event) => {
|
|
805
802
|
const storageEvent = event;
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
}
|
|
803
|
+
const area = storageEvent.storageArea === localStorage ? 'localStorage' : 'sessionStorage';
|
|
804
|
+
this.storageEvents.set({
|
|
805
|
+
key: storageEvent.key,
|
|
806
|
+
newValue: storageEvent.newValue ? this.deserializeValue(storageEvent.newValue) : null,
|
|
807
|
+
oldValue: storageEvent.oldValue ? this.deserializeValue(storageEvent.oldValue) : null,
|
|
808
|
+
storageArea: area,
|
|
809
|
+
});
|
|
814
810
|
});
|
|
815
811
|
}
|
|
816
812
|
}
|
|
@@ -837,50 +833,58 @@ class WebStorageService extends BrowserApiBaseService {
|
|
|
837
833
|
const prefix = options?.prefix || '';
|
|
838
834
|
return prefix ? `${prefix}:${key}` : key;
|
|
839
835
|
}
|
|
836
|
+
emitStorageChange(fullKey, newValue, oldValue, area) {
|
|
837
|
+
this.storageEvents.set({ key: fullKey, newValue, oldValue, storageArea: area });
|
|
838
|
+
}
|
|
840
839
|
// Local Storage Methods
|
|
841
840
|
setLocalStorage(key, value, options = {}) {
|
|
842
|
-
this.
|
|
841
|
+
this.ensureSupported();
|
|
843
842
|
try {
|
|
844
843
|
const serializedValue = this.serializeValue(value, options);
|
|
845
844
|
const fullKey = this.getKey(key, options);
|
|
845
|
+
const oldRaw = localStorage.getItem(fullKey);
|
|
846
|
+
const oldValue = oldRaw !== null ? this.deserializeValue(oldRaw, options) : null;
|
|
846
847
|
localStorage.setItem(fullKey, serializedValue);
|
|
848
|
+
this.emitStorageChange(fullKey, value, oldValue, 'localStorage');
|
|
847
849
|
return true;
|
|
848
850
|
}
|
|
849
851
|
catch (error) {
|
|
850
|
-
|
|
852
|
+
this.logError('Error setting localStorage:', error);
|
|
851
853
|
return false;
|
|
852
854
|
}
|
|
853
855
|
}
|
|
854
856
|
getLocalStorage(key, defaultValue = null, options = {}) {
|
|
855
|
-
this.
|
|
857
|
+
this.ensureSupported();
|
|
856
858
|
try {
|
|
857
859
|
const fullKey = this.getKey(key, options);
|
|
858
860
|
const value = localStorage.getItem(fullKey);
|
|
859
861
|
return value !== null ? this.deserializeValue(value, options) : defaultValue;
|
|
860
862
|
}
|
|
861
863
|
catch (error) {
|
|
862
|
-
|
|
864
|
+
this.logError('Error getting localStorage:', error);
|
|
863
865
|
return defaultValue;
|
|
864
866
|
}
|
|
865
867
|
}
|
|
866
868
|
removeLocalStorage(key, options = {}) {
|
|
867
|
-
this.
|
|
869
|
+
this.ensureSupported();
|
|
868
870
|
try {
|
|
869
871
|
const fullKey = this.getKey(key, options);
|
|
872
|
+
const oldRaw = localStorage.getItem(fullKey);
|
|
873
|
+
const oldValue = oldRaw !== null ? this.deserializeValue(oldRaw, options) : null;
|
|
870
874
|
localStorage.removeItem(fullKey);
|
|
875
|
+
this.emitStorageChange(fullKey, null, oldValue, 'localStorage');
|
|
871
876
|
return true;
|
|
872
877
|
}
|
|
873
878
|
catch (error) {
|
|
874
|
-
|
|
879
|
+
this.logError('Error removing localStorage:', error);
|
|
875
880
|
return false;
|
|
876
881
|
}
|
|
877
882
|
}
|
|
878
883
|
clearLocalStorage(options = {}) {
|
|
879
|
-
this.
|
|
884
|
+
this.ensureSupported();
|
|
880
885
|
try {
|
|
881
886
|
const prefix = options?.prefix;
|
|
882
887
|
if (prefix) {
|
|
883
|
-
// Only remove keys with the specified prefix
|
|
884
888
|
const keysToRemove = [];
|
|
885
889
|
for (let i = 0; i < localStorage.length; i++) {
|
|
886
890
|
const key = localStorage.key(i);
|
|
@@ -888,62 +892,72 @@ class WebStorageService extends BrowserApiBaseService {
|
|
|
888
892
|
keysToRemove.push(key);
|
|
889
893
|
}
|
|
890
894
|
}
|
|
891
|
-
keysToRemove.forEach((key) =>
|
|
895
|
+
keysToRemove.forEach((key) => {
|
|
896
|
+
const oldRaw = localStorage.getItem(key);
|
|
897
|
+
localStorage.removeItem(key);
|
|
898
|
+
this.emitStorageChange(key, null, oldRaw, 'localStorage');
|
|
899
|
+
});
|
|
892
900
|
}
|
|
893
901
|
else {
|
|
894
902
|
localStorage.clear();
|
|
903
|
+
this.emitStorageChange(null, null, null, 'localStorage');
|
|
895
904
|
}
|
|
896
905
|
return true;
|
|
897
906
|
}
|
|
898
907
|
catch (error) {
|
|
899
|
-
|
|
908
|
+
this.logError('Error clearing localStorage:', error);
|
|
900
909
|
return false;
|
|
901
910
|
}
|
|
902
911
|
}
|
|
903
912
|
// Session Storage Methods
|
|
904
913
|
setSessionStorage(key, value, options = {}) {
|
|
905
|
-
this.
|
|
914
|
+
this.ensureSupported();
|
|
906
915
|
try {
|
|
907
916
|
const serializedValue = this.serializeValue(value, options);
|
|
908
917
|
const fullKey = this.getKey(key, options);
|
|
918
|
+
const oldRaw = sessionStorage.getItem(fullKey);
|
|
919
|
+
const oldValue = oldRaw !== null ? this.deserializeValue(oldRaw, options) : null;
|
|
909
920
|
sessionStorage.setItem(fullKey, serializedValue);
|
|
921
|
+
this.emitStorageChange(fullKey, value, oldValue, 'sessionStorage');
|
|
910
922
|
return true;
|
|
911
923
|
}
|
|
912
924
|
catch (error) {
|
|
913
|
-
|
|
925
|
+
this.logError('Error setting sessionStorage:', error);
|
|
914
926
|
return false;
|
|
915
927
|
}
|
|
916
928
|
}
|
|
917
929
|
getSessionStorage(key, defaultValue = null, options = {}) {
|
|
918
|
-
this.
|
|
930
|
+
this.ensureSupported();
|
|
919
931
|
try {
|
|
920
932
|
const fullKey = this.getKey(key, options);
|
|
921
933
|
const value = sessionStorage.getItem(fullKey);
|
|
922
934
|
return value !== null ? this.deserializeValue(value, options) : defaultValue;
|
|
923
935
|
}
|
|
924
936
|
catch (error) {
|
|
925
|
-
|
|
937
|
+
this.logError('Error getting sessionStorage:', error);
|
|
926
938
|
return defaultValue;
|
|
927
939
|
}
|
|
928
940
|
}
|
|
929
941
|
removeSessionStorage(key, options = {}) {
|
|
930
|
-
this.
|
|
942
|
+
this.ensureSupported();
|
|
931
943
|
try {
|
|
932
944
|
const fullKey = this.getKey(key, options);
|
|
945
|
+
const oldRaw = sessionStorage.getItem(fullKey);
|
|
946
|
+
const oldValue = oldRaw !== null ? this.deserializeValue(oldRaw, options) : null;
|
|
933
947
|
sessionStorage.removeItem(fullKey);
|
|
948
|
+
this.emitStorageChange(fullKey, null, oldValue, 'sessionStorage');
|
|
934
949
|
return true;
|
|
935
950
|
}
|
|
936
951
|
catch (error) {
|
|
937
|
-
|
|
952
|
+
this.logError('Error removing sessionStorage:', error);
|
|
938
953
|
return false;
|
|
939
954
|
}
|
|
940
955
|
}
|
|
941
956
|
clearSessionStorage(options = {}) {
|
|
942
|
-
this.
|
|
957
|
+
this.ensureSupported();
|
|
943
958
|
try {
|
|
944
959
|
const prefix = options?.prefix;
|
|
945
960
|
if (prefix) {
|
|
946
|
-
// Only remove keys with the specified prefix
|
|
947
961
|
const keysToRemove = [];
|
|
948
962
|
for (let i = 0; i < sessionStorage.length; i++) {
|
|
949
963
|
const key = sessionStorage.key(i);
|
|
@@ -951,21 +965,26 @@ class WebStorageService extends BrowserApiBaseService {
|
|
|
951
965
|
keysToRemove.push(key);
|
|
952
966
|
}
|
|
953
967
|
}
|
|
954
|
-
keysToRemove.forEach((key) =>
|
|
968
|
+
keysToRemove.forEach((key) => {
|
|
969
|
+
const oldRaw = sessionStorage.getItem(key);
|
|
970
|
+
sessionStorage.removeItem(key);
|
|
971
|
+
this.emitStorageChange(key, null, oldRaw, 'sessionStorage');
|
|
972
|
+
});
|
|
955
973
|
}
|
|
956
974
|
else {
|
|
957
975
|
sessionStorage.clear();
|
|
976
|
+
this.emitStorageChange(null, null, null, 'sessionStorage');
|
|
958
977
|
}
|
|
959
978
|
return true;
|
|
960
979
|
}
|
|
961
980
|
catch (error) {
|
|
962
|
-
|
|
981
|
+
this.logError('Error clearing sessionStorage:', error);
|
|
963
982
|
return false;
|
|
964
983
|
}
|
|
965
984
|
}
|
|
966
985
|
// Utility Methods
|
|
967
986
|
getLocalStorageSize(options = {}) {
|
|
968
|
-
this.
|
|
987
|
+
this.ensureSupported();
|
|
969
988
|
let totalSize = 0;
|
|
970
989
|
const prefix = options?.prefix;
|
|
971
990
|
for (let i = 0; i < localStorage.length; i++) {
|
|
@@ -977,7 +996,7 @@ class WebStorageService extends BrowserApiBaseService {
|
|
|
977
996
|
return totalSize;
|
|
978
997
|
}
|
|
979
998
|
getSessionStorageSize(options = {}) {
|
|
980
|
-
this.
|
|
999
|
+
this.ensureSupported();
|
|
981
1000
|
let totalSize = 0;
|
|
982
1001
|
const prefix = options?.prefix;
|
|
983
1002
|
for (let i = 0; i < sessionStorage.length; i++) {
|
|
@@ -994,30 +1013,20 @@ class WebStorageService extends BrowserApiBaseService {
|
|
|
994
1013
|
prev.oldValue === curr.oldValue));
|
|
995
1014
|
}
|
|
996
1015
|
watchLocalStorage(key, options = {}) {
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
if (event.key === fullKey && event.storageArea === 'localStorage') {
|
|
1000
|
-
return event.newValue;
|
|
1001
|
-
}
|
|
1002
|
-
return this.getLocalStorage(key, null, options);
|
|
1003
|
-
}));
|
|
1016
|
+
const fullKey = this.getKey(key, options);
|
|
1017
|
+
return this.getStorageEvents().pipe(filter((event) => event.storageArea === 'localStorage' && (event.key === null || event.key === fullKey)), map((event) => event.newValue));
|
|
1004
1018
|
}
|
|
1005
1019
|
watchSessionStorage(key, options = {}) {
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
if (event.key === fullKey && event.storageArea === 'sessionStorage') {
|
|
1009
|
-
return event.newValue;
|
|
1010
|
-
}
|
|
1011
|
-
return this.getSessionStorage(key, null, options);
|
|
1012
|
-
}));
|
|
1020
|
+
const fullKey = this.getKey(key, options);
|
|
1021
|
+
return this.getStorageEvents().pipe(filter((event) => event.storageArea === 'sessionStorage' && (event.key === null || event.key === fullKey)), map((event) => event.newValue));
|
|
1013
1022
|
}
|
|
1014
1023
|
// Direct access to native storage APIs
|
|
1015
1024
|
getNativeLocalStorage() {
|
|
1016
|
-
this.
|
|
1025
|
+
this.ensureSupported();
|
|
1017
1026
|
return localStorage;
|
|
1018
1027
|
}
|
|
1019
1028
|
getNativeSessionStorage() {
|
|
1020
|
-
this.
|
|
1029
|
+
this.ensureSupported();
|
|
1021
1030
|
return sessionStorage;
|
|
1022
1031
|
}
|
|
1023
1032
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: WebStorageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
@@ -1029,21 +1038,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
|
|
|
1029
1038
|
|
|
1030
1039
|
class WebSocketService extends BrowserApiBaseService {
|
|
1031
1040
|
webSocket = null;
|
|
1032
|
-
statusSubject = new
|
|
1041
|
+
statusSubject = new BehaviorSubject({
|
|
1042
|
+
connected: false,
|
|
1043
|
+
connecting: false,
|
|
1044
|
+
reconnecting: false,
|
|
1045
|
+
reconnectAttempts: 0,
|
|
1046
|
+
});
|
|
1033
1047
|
messageSubject = new Subject();
|
|
1034
1048
|
reconnectAttempts = 0;
|
|
1035
1049
|
reconnectTimer = null;
|
|
1036
1050
|
heartbeatTimer = null;
|
|
1051
|
+
_cleanup = this.destroyRef.onDestroy(() => this.disconnect());
|
|
1037
1052
|
getApiName() {
|
|
1038
1053
|
return 'websocket';
|
|
1039
1054
|
}
|
|
1040
|
-
|
|
1055
|
+
ensureSupported() {
|
|
1056
|
+
super.ensureSupported();
|
|
1041
1057
|
if (typeof WebSocket === 'undefined') {
|
|
1042
1058
|
throw new Error('WebSocket API not supported in this browser');
|
|
1043
1059
|
}
|
|
1044
1060
|
}
|
|
1045
1061
|
connect(config) {
|
|
1046
|
-
this.
|
|
1062
|
+
this.ensureSupported();
|
|
1047
1063
|
return new Observable((observer) => {
|
|
1048
1064
|
this.disconnect(); // Disconnect existing connection if any
|
|
1049
1065
|
this.updateStatus({
|
|
@@ -1055,10 +1071,10 @@ class WebSocketService extends BrowserApiBaseService {
|
|
|
1055
1071
|
try {
|
|
1056
1072
|
this.webSocket = new WebSocket(config.url, config.protocols);
|
|
1057
1073
|
this.setupWebSocketHandlers(config);
|
|
1058
|
-
observer.next(this.
|
|
1074
|
+
observer.next(this.statusSubject.getValue());
|
|
1059
1075
|
}
|
|
1060
1076
|
catch (error) {
|
|
1061
|
-
|
|
1077
|
+
this.logError('Error creating WebSocket:', error);
|
|
1062
1078
|
this.updateStatus({
|
|
1063
1079
|
connected: false,
|
|
1064
1080
|
connecting: false,
|
|
@@ -1066,7 +1082,7 @@ class WebSocketService extends BrowserApiBaseService {
|
|
|
1066
1082
|
error: error instanceof Error ? error.message : 'Connection failed',
|
|
1067
1083
|
reconnectAttempts: 0,
|
|
1068
1084
|
});
|
|
1069
|
-
observer.next(this.
|
|
1085
|
+
observer.next(this.statusSubject.getValue());
|
|
1070
1086
|
}
|
|
1071
1087
|
return () => {
|
|
1072
1088
|
this.disconnect();
|
|
@@ -1113,15 +1129,18 @@ class WebSocketService extends BrowserApiBaseService {
|
|
|
1113
1129
|
return this.statusSubject.asObservable();
|
|
1114
1130
|
}
|
|
1115
1131
|
getMessages() {
|
|
1132
|
+
return this.messageSubject.asObservable();
|
|
1133
|
+
}
|
|
1134
|
+
getMessagesByType(type) {
|
|
1116
1135
|
return this.messageSubject
|
|
1117
1136
|
.asObservable()
|
|
1118
|
-
.pipe(filter((msg) =>
|
|
1137
|
+
.pipe(filter((msg) => msg.type === type));
|
|
1119
1138
|
}
|
|
1120
1139
|
setupWebSocketHandlers(config) {
|
|
1121
1140
|
if (!this.webSocket)
|
|
1122
1141
|
return;
|
|
1123
1142
|
this.webSocket.onopen = () => {
|
|
1124
|
-
|
|
1143
|
+
this.logInfo(`Connected to: ${config.url}`);
|
|
1125
1144
|
this.reconnectAttempts = 0;
|
|
1126
1145
|
this.updateStatus({
|
|
1127
1146
|
connected: true,
|
|
@@ -1135,7 +1154,7 @@ class WebSocketService extends BrowserApiBaseService {
|
|
|
1135
1154
|
}
|
|
1136
1155
|
};
|
|
1137
1156
|
this.webSocket.onclose = (event) => {
|
|
1138
|
-
|
|
1157
|
+
this.logInfo(`Connection closed: ${event.code} ${event.reason}`);
|
|
1139
1158
|
this.updateStatus({
|
|
1140
1159
|
connected: false,
|
|
1141
1160
|
connecting: false,
|
|
@@ -1148,7 +1167,7 @@ class WebSocketService extends BrowserApiBaseService {
|
|
|
1148
1167
|
}
|
|
1149
1168
|
};
|
|
1150
1169
|
this.webSocket.onerror = (error) => {
|
|
1151
|
-
|
|
1170
|
+
this.logError('WebSocket error:', error);
|
|
1152
1171
|
this.updateStatus({
|
|
1153
1172
|
connected: false,
|
|
1154
1173
|
connecting: false,
|
|
@@ -1163,7 +1182,7 @@ class WebSocketService extends BrowserApiBaseService {
|
|
|
1163
1182
|
this.messageSubject.next(message);
|
|
1164
1183
|
}
|
|
1165
1184
|
catch (error) {
|
|
1166
|
-
|
|
1185
|
+
this.logError('Error parsing message:', error);
|
|
1167
1186
|
}
|
|
1168
1187
|
};
|
|
1169
1188
|
}
|
|
@@ -1179,7 +1198,7 @@ class WebSocketService extends BrowserApiBaseService {
|
|
|
1179
1198
|
}
|
|
1180
1199
|
attemptReconnect(config) {
|
|
1181
1200
|
if (this.reconnectAttempts >= (config.maxReconnectAttempts || 5)) {
|
|
1182
|
-
|
|
1201
|
+
this.logInfo('Max reconnect attempts reached');
|
|
1183
1202
|
return;
|
|
1184
1203
|
}
|
|
1185
1204
|
this.reconnectAttempts++;
|
|
@@ -1190,23 +1209,14 @@ class WebSocketService extends BrowserApiBaseService {
|
|
|
1190
1209
|
reconnectAttempts: this.reconnectAttempts,
|
|
1191
1210
|
});
|
|
1192
1211
|
this.reconnectTimer = setTimeout(() => {
|
|
1193
|
-
|
|
1212
|
+
this.logInfo(`Reconnect attempt ${this.reconnectAttempts}`);
|
|
1194
1213
|
this.connect(config);
|
|
1195
1214
|
}, config.reconnectInterval || 3000);
|
|
1196
1215
|
}
|
|
1197
1216
|
updateStatus(status) {
|
|
1198
|
-
const
|
|
1199
|
-
const newStatus = { ...currentStatus, ...status };
|
|
1217
|
+
const newStatus = { ...this.statusSubject.getValue(), ...status };
|
|
1200
1218
|
this.statusSubject.next(newStatus);
|
|
1201
1219
|
}
|
|
1202
|
-
getCurrentStatus() {
|
|
1203
|
-
return {
|
|
1204
|
-
connected: this.webSocket?.readyState === WebSocket.OPEN,
|
|
1205
|
-
connecting: false,
|
|
1206
|
-
reconnecting: false,
|
|
1207
|
-
reconnectAttempts: this.reconnectAttempts,
|
|
1208
|
-
};
|
|
1209
|
-
}
|
|
1210
1220
|
// Direct access to native WebSocket
|
|
1211
1221
|
getNativeWebSocket() {
|
|
1212
1222
|
return this.webSocket;
|
|
@@ -1225,21 +1235,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
|
|
|
1225
1235
|
}] });
|
|
1226
1236
|
|
|
1227
1237
|
class WebWorkerService extends BrowserApiBaseService {
|
|
1228
|
-
destroyRef = inject(DestroyRef);
|
|
1229
1238
|
workers = new Map();
|
|
1230
1239
|
workerStatuses = new Map();
|
|
1231
1240
|
workerMessages = new Map();
|
|
1232
1241
|
currentWorkerStatuses = new Map();
|
|
1242
|
+
_cleanup = this.destroyRef.onDestroy(() => this.terminateAllWorkers());
|
|
1233
1243
|
getApiName() {
|
|
1234
1244
|
return 'webworker';
|
|
1235
1245
|
}
|
|
1236
|
-
|
|
1246
|
+
ensureSupported() {
|
|
1247
|
+
super.ensureSupported();
|
|
1237
1248
|
if (typeof Worker === 'undefined') {
|
|
1238
1249
|
throw new Error('Web Workers not supported in this browser');
|
|
1239
1250
|
}
|
|
1240
1251
|
}
|
|
1241
1252
|
createWorker(name, scriptUrl) {
|
|
1242
|
-
this.
|
|
1253
|
+
this.ensureSupported();
|
|
1243
1254
|
return new Observable((observer) => {
|
|
1244
1255
|
if (this.workers.has(name)) {
|
|
1245
1256
|
observer.next(this.currentWorkerStatuses.get(name));
|
|
@@ -1261,7 +1272,7 @@ class WebWorkerService extends BrowserApiBaseService {
|
|
|
1261
1272
|
observer.next(status);
|
|
1262
1273
|
}
|
|
1263
1274
|
catch (error) {
|
|
1264
|
-
|
|
1275
|
+
this.logError(`Failed to create worker ${name}:`, error);
|
|
1265
1276
|
const status = {
|
|
1266
1277
|
initialized: false,
|
|
1267
1278
|
running: false,
|
|
@@ -1295,7 +1306,7 @@ class WebWorkerService extends BrowserApiBaseService {
|
|
|
1295
1306
|
postMessage(workerName, task) {
|
|
1296
1307
|
const worker = this.workers.get(workerName);
|
|
1297
1308
|
if (!worker) {
|
|
1298
|
-
|
|
1309
|
+
this.logError(`Worker ${workerName} not found`);
|
|
1299
1310
|
return;
|
|
1300
1311
|
}
|
|
1301
1312
|
try {
|
|
@@ -1313,7 +1324,7 @@ class WebWorkerService extends BrowserApiBaseService {
|
|
|
1313
1324
|
}
|
|
1314
1325
|
}
|
|
1315
1326
|
catch (error) {
|
|
1316
|
-
|
|
1327
|
+
this.logError(`Failed to post message to worker ${workerName}:`, error);
|
|
1317
1328
|
}
|
|
1318
1329
|
}
|
|
1319
1330
|
getMessages(workerName) {
|
|
@@ -1352,7 +1363,7 @@ class WebWorkerService extends BrowserApiBaseService {
|
|
|
1352
1363
|
this.workerMessages.get(name).next(message);
|
|
1353
1364
|
};
|
|
1354
1365
|
worker.onerror = (error) => {
|
|
1355
|
-
|
|
1366
|
+
this.logError(`Worker ${name} error:`, error);
|
|
1356
1367
|
const status = {
|
|
1357
1368
|
initialized: true,
|
|
1358
1369
|
running: false,
|
|
@@ -1724,7 +1735,7 @@ class ScreenWakeLockService extends BrowserApiBaseService {
|
|
|
1724
1735
|
return 'screen-wake-lock';
|
|
1725
1736
|
}
|
|
1726
1737
|
isSupported() {
|
|
1727
|
-
return
|
|
1738
|
+
return this.isBrowserEnvironment() && 'wakeLock' in navigator;
|
|
1728
1739
|
}
|
|
1729
1740
|
get isActive() {
|
|
1730
1741
|
return this.sentinel !== null && !this.sentinel.released;
|
|
@@ -1745,7 +1756,7 @@ class ScreenWakeLockService extends BrowserApiBaseService {
|
|
|
1745
1756
|
return { active: true, type, released: false };
|
|
1746
1757
|
}
|
|
1747
1758
|
catch (error) {
|
|
1748
|
-
|
|
1759
|
+
this.logError('Failed to acquire wake lock:', error);
|
|
1749
1760
|
throw this.createError('Failed to acquire wake lock', error);
|
|
1750
1761
|
}
|
|
1751
1762
|
}
|
|
@@ -1961,10 +1972,8 @@ class FileSystemAccessService extends BrowserApiBaseService {
|
|
|
1961
1972
|
get win() {
|
|
1962
1973
|
return window;
|
|
1963
1974
|
}
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
throw new Error('File System Access API not available in server environment');
|
|
1967
|
-
}
|
|
1975
|
+
ensureSupported() {
|
|
1976
|
+
super.ensureSupported();
|
|
1968
1977
|
if (!('showOpenFilePicker' in window)) {
|
|
1969
1978
|
throw new Error('File System Access API not supported in this browser');
|
|
1970
1979
|
}
|
|
@@ -1973,7 +1982,7 @@ class FileSystemAccessService extends BrowserApiBaseService {
|
|
|
1973
1982
|
}
|
|
1974
1983
|
}
|
|
1975
1984
|
async openFile(options = {}) {
|
|
1976
|
-
this.
|
|
1985
|
+
this.ensureSupported();
|
|
1977
1986
|
try {
|
|
1978
1987
|
const handles = await this.win.showOpenFilePicker(options);
|
|
1979
1988
|
return Promise.all(handles.map((h) => h.getFile()));
|
|
@@ -1982,12 +1991,12 @@ class FileSystemAccessService extends BrowserApiBaseService {
|
|
|
1982
1991
|
if (error instanceof DOMException && error.name === 'AbortError') {
|
|
1983
1992
|
return [];
|
|
1984
1993
|
}
|
|
1985
|
-
|
|
1994
|
+
this.logError('Error opening file:', error);
|
|
1986
1995
|
throw error;
|
|
1987
1996
|
}
|
|
1988
1997
|
}
|
|
1989
1998
|
async saveFile(content, options = {}) {
|
|
1990
|
-
this.
|
|
1999
|
+
this.ensureSupported();
|
|
1991
2000
|
if (!this.win.showSaveFilePicker) {
|
|
1992
2001
|
throw new Error('showSaveFilePicker not supported');
|
|
1993
2002
|
}
|
|
@@ -2001,12 +2010,12 @@ class FileSystemAccessService extends BrowserApiBaseService {
|
|
|
2001
2010
|
if (error instanceof DOMException && error.name === 'AbortError') {
|
|
2002
2011
|
return;
|
|
2003
2012
|
}
|
|
2004
|
-
|
|
2013
|
+
this.logError('Error saving file:', error);
|
|
2005
2014
|
throw error;
|
|
2006
2015
|
}
|
|
2007
2016
|
}
|
|
2008
2017
|
async openDirectory(options = {}) {
|
|
2009
|
-
this.
|
|
2018
|
+
this.ensureSupported();
|
|
2010
2019
|
if (!this.win.showDirectoryPicker) {
|
|
2011
2020
|
throw new Error('showDirectoryPicker not supported');
|
|
2012
2021
|
}
|
|
@@ -2017,7 +2026,7 @@ class FileSystemAccessService extends BrowserApiBaseService {
|
|
|
2017
2026
|
if (error instanceof DOMException && error.name === 'AbortError') {
|
|
2018
2027
|
return null;
|
|
2019
2028
|
}
|
|
2020
|
-
|
|
2029
|
+
this.logError('Error opening directory:', error);
|
|
2021
2030
|
throw error;
|
|
2022
2031
|
}
|
|
2023
2032
|
}
|
|
@@ -2084,7 +2093,7 @@ class MediaRecorderService extends BrowserApiBaseService {
|
|
|
2084
2093
|
this.recorder.start(timeslice);
|
|
2085
2094
|
}
|
|
2086
2095
|
catch (error) {
|
|
2087
|
-
|
|
2096
|
+
this.logError('Failed to start recording:', error);
|
|
2088
2097
|
throw this.createError('Failed to start recording', error);
|
|
2089
2098
|
}
|
|
2090
2099
|
}
|
|
@@ -2170,7 +2179,7 @@ class ServerSentEventsService extends ConnectionRegistryBaseService {
|
|
|
2170
2179
|
observer.error(new Error('SSE connection closed unexpectedly'));
|
|
2171
2180
|
}
|
|
2172
2181
|
else {
|
|
2173
|
-
|
|
2182
|
+
this.logWarn('SSE connection error, reconnecting...');
|
|
2174
2183
|
}
|
|
2175
2184
|
};
|
|
2176
2185
|
source.addEventListener('message', messageHandler);
|
|
@@ -3365,218 +3374,253 @@ const permissionGuard = (permission) => {
|
|
|
3365
3374
|
};
|
|
3366
3375
|
};
|
|
3367
3376
|
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
enableGeolocation: true,
|
|
3371
|
-
enableNotifications: true,
|
|
3372
|
-
enableClipboard: true,
|
|
3373
|
-
enableBattery: false,
|
|
3374
|
-
enableMediaDevices: true,
|
|
3375
|
-
enableWebShare: false,
|
|
3376
|
-
enableWebStorage: false,
|
|
3377
|
-
enableWebSocket: false,
|
|
3378
|
-
enableWebWorker: false,
|
|
3379
|
-
enableIntersectionObserver: false,
|
|
3380
|
-
enableResizeObserver: false,
|
|
3381
|
-
enablePageVisibility: false,
|
|
3382
|
-
enableBroadcastChannel: false,
|
|
3383
|
-
enableNetworkInformation: false,
|
|
3384
|
-
enableScreenWakeLock: false,
|
|
3385
|
-
enableScreenOrientation: false,
|
|
3386
|
-
enableFullscreen: false,
|
|
3387
|
-
enableFileSystemAccess: false,
|
|
3388
|
-
enableMediaRecorder: false,
|
|
3389
|
-
enableServerSentEvents: false,
|
|
3390
|
-
enableVibration: false,
|
|
3391
|
-
enableSpeechSynthesis: false,
|
|
3392
|
-
enableMutationObserver: false,
|
|
3393
|
-
enablePerformanceObserver: false,
|
|
3394
|
-
enableIdleDetector: false,
|
|
3395
|
-
enableEyeDropper: false,
|
|
3396
|
-
enableBarcodeDetector: false,
|
|
3397
|
-
enableWebAudio: false,
|
|
3398
|
-
enableGamepad: false,
|
|
3399
|
-
enableWebBluetooth: false,
|
|
3400
|
-
enableWebUsb: false,
|
|
3401
|
-
enableWebNfc: false,
|
|
3402
|
-
enablePaymentRequest: false,
|
|
3403
|
-
enableCredentialManagement: false,
|
|
3404
|
-
};
|
|
3405
|
-
function provideBrowserWebApis(config = {}) {
|
|
3406
|
-
const mergedConfig = { ...defaultBrowserWebApisConfig, ...config };
|
|
3407
|
-
const providers = [PermissionsService];
|
|
3408
|
-
const conditionalProviders = [
|
|
3409
|
-
[mergedConfig.enableCamera, CameraService],
|
|
3410
|
-
[mergedConfig.enableGeolocation, GeolocationService],
|
|
3411
|
-
[mergedConfig.enableNotifications, NotificationService],
|
|
3412
|
-
[mergedConfig.enableClipboard, ClipboardService],
|
|
3413
|
-
[mergedConfig.enableMediaDevices, MediaDevicesService],
|
|
3414
|
-
[mergedConfig.enableBattery, BatteryService],
|
|
3415
|
-
[mergedConfig.enableWebShare, WebShareService],
|
|
3416
|
-
[mergedConfig.enableWebStorage, WebStorageService],
|
|
3417
|
-
[mergedConfig.enableWebSocket, WebSocketService],
|
|
3418
|
-
[mergedConfig.enableWebWorker, WebWorkerService],
|
|
3419
|
-
[mergedConfig.enableIntersectionObserver, IntersectionObserverService],
|
|
3420
|
-
[mergedConfig.enableResizeObserver, ResizeObserverService],
|
|
3421
|
-
[mergedConfig.enablePageVisibility, PageVisibilityService],
|
|
3422
|
-
[mergedConfig.enableBroadcastChannel, BroadcastChannelService],
|
|
3423
|
-
[mergedConfig.enableNetworkInformation, NetworkInformationService],
|
|
3424
|
-
[mergedConfig.enableScreenWakeLock, ScreenWakeLockService],
|
|
3425
|
-
[mergedConfig.enableScreenOrientation, ScreenOrientationService],
|
|
3426
|
-
[mergedConfig.enableFullscreen, FullscreenService],
|
|
3427
|
-
[mergedConfig.enableFileSystemAccess, FileSystemAccessService],
|
|
3428
|
-
[mergedConfig.enableMediaRecorder, MediaRecorderService],
|
|
3429
|
-
[mergedConfig.enableServerSentEvents, ServerSentEventsService],
|
|
3430
|
-
[mergedConfig.enableVibration, VibrationService],
|
|
3431
|
-
[mergedConfig.enableSpeechSynthesis, SpeechSynthesisService],
|
|
3432
|
-
[mergedConfig.enableMutationObserver, MutationObserverService],
|
|
3433
|
-
[mergedConfig.enablePerformanceObserver, PerformanceObserverService],
|
|
3434
|
-
[mergedConfig.enableIdleDetector, IdleDetectorService],
|
|
3435
|
-
[mergedConfig.enableEyeDropper, EyeDropperService],
|
|
3436
|
-
[mergedConfig.enableBarcodeDetector, BarcodeDetectorService],
|
|
3437
|
-
[mergedConfig.enableWebAudio, WebAudioService],
|
|
3438
|
-
[mergedConfig.enableGamepad, GamepadService],
|
|
3439
|
-
[mergedConfig.enableWebBluetooth, WebBluetoothService],
|
|
3440
|
-
[mergedConfig.enableWebUsb, WebUsbService],
|
|
3441
|
-
[mergedConfig.enableWebNfc, WebNfcService],
|
|
3442
|
-
[mergedConfig.enablePaymentRequest, PaymentRequestService],
|
|
3443
|
-
[mergedConfig.enableCredentialManagement, CredentialManagementService],
|
|
3444
|
-
];
|
|
3445
|
-
for (const [enabled, provider] of conditionalProviders) {
|
|
3446
|
-
if (enabled) {
|
|
3447
|
-
providers.push(provider);
|
|
3448
|
-
}
|
|
3449
|
-
}
|
|
3450
|
-
return makeEnvironmentProviders(providers);
|
|
3377
|
+
function providePermissions() {
|
|
3378
|
+
return makeEnvironmentProviders([PermissionsService]);
|
|
3451
3379
|
}
|
|
3452
|
-
|
|
3380
|
+
|
|
3453
3381
|
function provideCamera() {
|
|
3454
|
-
return makeEnvironmentProviders([
|
|
3382
|
+
return makeEnvironmentProviders([CameraService]);
|
|
3455
3383
|
}
|
|
3384
|
+
|
|
3456
3385
|
function provideGeolocation() {
|
|
3457
3386
|
return makeEnvironmentProviders([PermissionsService, GeolocationService]);
|
|
3458
3387
|
}
|
|
3388
|
+
|
|
3459
3389
|
function provideNotifications() {
|
|
3460
3390
|
return makeEnvironmentProviders([PermissionsService, NotificationService]);
|
|
3461
3391
|
}
|
|
3392
|
+
|
|
3462
3393
|
function provideClipboard() {
|
|
3463
|
-
return makeEnvironmentProviders([
|
|
3394
|
+
return makeEnvironmentProviders([ClipboardService]);
|
|
3464
3395
|
}
|
|
3396
|
+
|
|
3465
3397
|
function provideMediaDevices() {
|
|
3466
3398
|
return makeEnvironmentProviders([PermissionsService, MediaDevicesService]);
|
|
3467
3399
|
}
|
|
3400
|
+
|
|
3401
|
+
function provideScreenWakeLock() {
|
|
3402
|
+
return makeEnvironmentProviders([PermissionsService, ScreenWakeLockService]);
|
|
3403
|
+
}
|
|
3404
|
+
|
|
3405
|
+
function provideFileSystemAccess() {
|
|
3406
|
+
return makeEnvironmentProviders([PermissionsService, FileSystemAccessService]);
|
|
3407
|
+
}
|
|
3408
|
+
|
|
3409
|
+
function provideMediaRecorder() {
|
|
3410
|
+
return makeEnvironmentProviders([PermissionsService, MediaRecorderService]);
|
|
3411
|
+
}
|
|
3412
|
+
|
|
3413
|
+
function provideIdleDetector() {
|
|
3414
|
+
return makeEnvironmentProviders([PermissionsService, IdleDetectorService]);
|
|
3415
|
+
}
|
|
3416
|
+
|
|
3468
3417
|
function provideBattery() {
|
|
3469
3418
|
return makeEnvironmentProviders([BatteryService]);
|
|
3470
3419
|
}
|
|
3420
|
+
|
|
3471
3421
|
function provideWebShare() {
|
|
3472
3422
|
return makeEnvironmentProviders([WebShareService]);
|
|
3473
3423
|
}
|
|
3424
|
+
|
|
3474
3425
|
function provideWebStorage() {
|
|
3475
3426
|
return makeEnvironmentProviders([WebStorageService]);
|
|
3476
3427
|
}
|
|
3428
|
+
|
|
3477
3429
|
function provideWebSocket() {
|
|
3478
3430
|
return makeEnvironmentProviders([WebSocketService]);
|
|
3479
3431
|
}
|
|
3432
|
+
|
|
3480
3433
|
function provideWebWorker() {
|
|
3481
3434
|
return makeEnvironmentProviders([WebWorkerService]);
|
|
3482
3435
|
}
|
|
3483
|
-
|
|
3484
|
-
return makeEnvironmentProviders([PermissionsService]);
|
|
3485
|
-
}
|
|
3486
|
-
// Combined providers for common use cases
|
|
3487
|
-
function provideMediaApis() {
|
|
3488
|
-
return makeEnvironmentProviders([PermissionsService, CameraService, MediaDevicesService]);
|
|
3489
|
-
}
|
|
3490
|
-
function provideLocationApis() {
|
|
3491
|
-
return makeEnvironmentProviders([PermissionsService, GeolocationService]);
|
|
3492
|
-
}
|
|
3493
|
-
function provideStorageApis() {
|
|
3494
|
-
return makeEnvironmentProviders([PermissionsService, ClipboardService, WebStorageService]);
|
|
3495
|
-
}
|
|
3496
|
-
function provideCommunicationApis() {
|
|
3497
|
-
return makeEnvironmentProviders([
|
|
3498
|
-
PermissionsService,
|
|
3499
|
-
NotificationService,
|
|
3500
|
-
WebShareService,
|
|
3501
|
-
WebSocketService,
|
|
3502
|
-
]);
|
|
3503
|
-
}
|
|
3436
|
+
|
|
3504
3437
|
function provideIntersectionObserver() {
|
|
3505
3438
|
return makeEnvironmentProviders([IntersectionObserverService]);
|
|
3506
3439
|
}
|
|
3440
|
+
|
|
3507
3441
|
function provideResizeObserver() {
|
|
3508
3442
|
return makeEnvironmentProviders([ResizeObserverService]);
|
|
3509
3443
|
}
|
|
3444
|
+
|
|
3510
3445
|
function providePageVisibility() {
|
|
3511
3446
|
return makeEnvironmentProviders([PageVisibilityService]);
|
|
3512
3447
|
}
|
|
3448
|
+
|
|
3513
3449
|
function provideBroadcastChannel() {
|
|
3514
3450
|
return makeEnvironmentProviders([BroadcastChannelService]);
|
|
3515
3451
|
}
|
|
3452
|
+
|
|
3516
3453
|
function provideNetworkInformation() {
|
|
3517
3454
|
return makeEnvironmentProviders([NetworkInformationService]);
|
|
3518
3455
|
}
|
|
3519
|
-
|
|
3520
|
-
return makeEnvironmentProviders([PermissionsService, ScreenWakeLockService]);
|
|
3521
|
-
}
|
|
3456
|
+
|
|
3522
3457
|
function provideScreenOrientation() {
|
|
3523
3458
|
return makeEnvironmentProviders([ScreenOrientationService]);
|
|
3524
3459
|
}
|
|
3460
|
+
|
|
3525
3461
|
function provideFullscreen() {
|
|
3526
3462
|
return makeEnvironmentProviders([FullscreenService]);
|
|
3527
3463
|
}
|
|
3528
|
-
|
|
3529
|
-
return makeEnvironmentProviders([PermissionsService, FileSystemAccessService]);
|
|
3530
|
-
}
|
|
3531
|
-
function provideMediaRecorder() {
|
|
3532
|
-
return makeEnvironmentProviders([PermissionsService, MediaRecorderService]);
|
|
3533
|
-
}
|
|
3464
|
+
|
|
3534
3465
|
function provideServerSentEvents() {
|
|
3535
3466
|
return makeEnvironmentProviders([ServerSentEventsService]);
|
|
3536
3467
|
}
|
|
3468
|
+
|
|
3537
3469
|
function provideVibration() {
|
|
3538
3470
|
return makeEnvironmentProviders([VibrationService]);
|
|
3539
3471
|
}
|
|
3472
|
+
|
|
3540
3473
|
function provideSpeechSynthesis() {
|
|
3541
3474
|
return makeEnvironmentProviders([SpeechSynthesisService]);
|
|
3542
3475
|
}
|
|
3476
|
+
|
|
3543
3477
|
function provideMutationObserver() {
|
|
3544
3478
|
return makeEnvironmentProviders([MutationObserverService]);
|
|
3545
3479
|
}
|
|
3480
|
+
|
|
3546
3481
|
function providePerformanceObserver() {
|
|
3547
3482
|
return makeEnvironmentProviders([PerformanceObserverService]);
|
|
3548
3483
|
}
|
|
3549
|
-
|
|
3550
|
-
return makeEnvironmentProviders([PermissionsService, IdleDetectorService]);
|
|
3551
|
-
}
|
|
3484
|
+
|
|
3552
3485
|
function provideEyeDropper() {
|
|
3553
3486
|
return makeEnvironmentProviders([EyeDropperService]);
|
|
3554
3487
|
}
|
|
3488
|
+
|
|
3555
3489
|
function provideBarcodeDetector() {
|
|
3556
3490
|
return makeEnvironmentProviders([BarcodeDetectorService]);
|
|
3557
3491
|
}
|
|
3492
|
+
|
|
3558
3493
|
function provideWebAudio() {
|
|
3559
3494
|
return makeEnvironmentProviders([WebAudioService]);
|
|
3560
3495
|
}
|
|
3496
|
+
|
|
3561
3497
|
function provideGamepad() {
|
|
3562
3498
|
return makeEnvironmentProviders([GamepadService]);
|
|
3563
3499
|
}
|
|
3500
|
+
|
|
3564
3501
|
function provideWebBluetooth() {
|
|
3565
3502
|
return makeEnvironmentProviders([WebBluetoothService]);
|
|
3566
3503
|
}
|
|
3504
|
+
|
|
3567
3505
|
function provideWebUsb() {
|
|
3568
3506
|
return makeEnvironmentProviders([WebUsbService]);
|
|
3569
3507
|
}
|
|
3508
|
+
|
|
3570
3509
|
function provideWebNfc() {
|
|
3571
3510
|
return makeEnvironmentProviders([WebNfcService]);
|
|
3572
3511
|
}
|
|
3512
|
+
|
|
3573
3513
|
function providePaymentRequest() {
|
|
3574
3514
|
return makeEnvironmentProviders([PaymentRequestService]);
|
|
3575
3515
|
}
|
|
3516
|
+
|
|
3576
3517
|
function provideCredentialManagement() {
|
|
3577
3518
|
return makeEnvironmentProviders([CredentialManagementService]);
|
|
3578
3519
|
}
|
|
3579
3520
|
|
|
3521
|
+
function provideMediaApis() {
|
|
3522
|
+
return makeEnvironmentProviders([PermissionsService, CameraService, MediaDevicesService]);
|
|
3523
|
+
}
|
|
3524
|
+
function provideLocationApis() {
|
|
3525
|
+
return makeEnvironmentProviders([PermissionsService, GeolocationService]);
|
|
3526
|
+
}
|
|
3527
|
+
function provideStorageApis() {
|
|
3528
|
+
return makeEnvironmentProviders([PermissionsService, ClipboardService, WebStorageService]);
|
|
3529
|
+
}
|
|
3530
|
+
function provideCommunicationApis() {
|
|
3531
|
+
return makeEnvironmentProviders([
|
|
3532
|
+
PermissionsService,
|
|
3533
|
+
NotificationService,
|
|
3534
|
+
WebShareService,
|
|
3535
|
+
WebSocketService,
|
|
3536
|
+
]);
|
|
3537
|
+
}
|
|
3538
|
+
|
|
3539
|
+
const defaultBrowserWebApisConfig = {
|
|
3540
|
+
enableCamera: true,
|
|
3541
|
+
enableGeolocation: true,
|
|
3542
|
+
enableNotifications: true,
|
|
3543
|
+
enableClipboard: true,
|
|
3544
|
+
enableBattery: false,
|
|
3545
|
+
enableMediaDevices: true,
|
|
3546
|
+
enableWebShare: false,
|
|
3547
|
+
enableWebStorage: false,
|
|
3548
|
+
enableWebSocket: false,
|
|
3549
|
+
enableWebWorker: false,
|
|
3550
|
+
enableIntersectionObserver: false,
|
|
3551
|
+
enableResizeObserver: false,
|
|
3552
|
+
enablePageVisibility: false,
|
|
3553
|
+
enableBroadcastChannel: false,
|
|
3554
|
+
enableNetworkInformation: false,
|
|
3555
|
+
enableScreenWakeLock: false,
|
|
3556
|
+
enableScreenOrientation: false,
|
|
3557
|
+
enableFullscreen: false,
|
|
3558
|
+
enableFileSystemAccess: false,
|
|
3559
|
+
enableMediaRecorder: false,
|
|
3560
|
+
enableServerSentEvents: false,
|
|
3561
|
+
enableVibration: false,
|
|
3562
|
+
enableSpeechSynthesis: false,
|
|
3563
|
+
enableMutationObserver: false,
|
|
3564
|
+
enablePerformanceObserver: false,
|
|
3565
|
+
enableIdleDetector: false,
|
|
3566
|
+
enableEyeDropper: false,
|
|
3567
|
+
enableBarcodeDetector: false,
|
|
3568
|
+
enableWebAudio: false,
|
|
3569
|
+
enableGamepad: false,
|
|
3570
|
+
enableWebBluetooth: false,
|
|
3571
|
+
enableWebUsb: false,
|
|
3572
|
+
enableWebNfc: false,
|
|
3573
|
+
enablePaymentRequest: false,
|
|
3574
|
+
enableCredentialManagement: false,
|
|
3575
|
+
};
|
|
3576
|
+
function provideBrowserWebApis(config = {}) {
|
|
3577
|
+
const mergedConfig = { ...defaultBrowserWebApisConfig, ...config };
|
|
3578
|
+
const providers = [PermissionsService];
|
|
3579
|
+
const conditionalProviders = [
|
|
3580
|
+
[mergedConfig.enableCamera, CameraService],
|
|
3581
|
+
[mergedConfig.enableGeolocation, GeolocationService],
|
|
3582
|
+
[mergedConfig.enableNotifications, NotificationService],
|
|
3583
|
+
[mergedConfig.enableClipboard, ClipboardService],
|
|
3584
|
+
[mergedConfig.enableMediaDevices, MediaDevicesService],
|
|
3585
|
+
[mergedConfig.enableBattery, BatteryService],
|
|
3586
|
+
[mergedConfig.enableWebShare, WebShareService],
|
|
3587
|
+
[mergedConfig.enableWebStorage, WebStorageService],
|
|
3588
|
+
[mergedConfig.enableWebSocket, WebSocketService],
|
|
3589
|
+
[mergedConfig.enableWebWorker, WebWorkerService],
|
|
3590
|
+
[mergedConfig.enableIntersectionObserver, IntersectionObserverService],
|
|
3591
|
+
[mergedConfig.enableResizeObserver, ResizeObserverService],
|
|
3592
|
+
[mergedConfig.enablePageVisibility, PageVisibilityService],
|
|
3593
|
+
[mergedConfig.enableBroadcastChannel, BroadcastChannelService],
|
|
3594
|
+
[mergedConfig.enableNetworkInformation, NetworkInformationService],
|
|
3595
|
+
[mergedConfig.enableScreenWakeLock, ScreenWakeLockService],
|
|
3596
|
+
[mergedConfig.enableScreenOrientation, ScreenOrientationService],
|
|
3597
|
+
[mergedConfig.enableFullscreen, FullscreenService],
|
|
3598
|
+
[mergedConfig.enableFileSystemAccess, FileSystemAccessService],
|
|
3599
|
+
[mergedConfig.enableMediaRecorder, MediaRecorderService],
|
|
3600
|
+
[mergedConfig.enableServerSentEvents, ServerSentEventsService],
|
|
3601
|
+
[mergedConfig.enableVibration, VibrationService],
|
|
3602
|
+
[mergedConfig.enableSpeechSynthesis, SpeechSynthesisService],
|
|
3603
|
+
[mergedConfig.enableMutationObserver, MutationObserverService],
|
|
3604
|
+
[mergedConfig.enablePerformanceObserver, PerformanceObserverService],
|
|
3605
|
+
[mergedConfig.enableIdleDetector, IdleDetectorService],
|
|
3606
|
+
[mergedConfig.enableEyeDropper, EyeDropperService],
|
|
3607
|
+
[mergedConfig.enableBarcodeDetector, BarcodeDetectorService],
|
|
3608
|
+
[mergedConfig.enableWebAudio, WebAudioService],
|
|
3609
|
+
[mergedConfig.enableGamepad, GamepadService],
|
|
3610
|
+
[mergedConfig.enableWebBluetooth, WebBluetoothService],
|
|
3611
|
+
[mergedConfig.enableWebUsb, WebUsbService],
|
|
3612
|
+
[mergedConfig.enableWebNfc, WebNfcService],
|
|
3613
|
+
[mergedConfig.enablePaymentRequest, PaymentRequestService],
|
|
3614
|
+
[mergedConfig.enableCredentialManagement, CredentialManagementService],
|
|
3615
|
+
];
|
|
3616
|
+
for (const [enabled, provider] of conditionalProviders) {
|
|
3617
|
+
if (enabled) {
|
|
3618
|
+
providers.push(provider);
|
|
3619
|
+
}
|
|
3620
|
+
}
|
|
3621
|
+
return makeEnvironmentProviders(providers);
|
|
3622
|
+
}
|
|
3623
|
+
|
|
3580
3624
|
// Browser Web APIs Services
|
|
3581
3625
|
// Version
|
|
3582
3626
|
const version = '0.1.0';
|
|
@@ -3585,4 +3629,4 @@ const version = '0.1.0';
|
|
|
3585
3629
|
* Generated bundle index. Do not edit.
|
|
3586
3630
|
*/
|
|
3587
3631
|
|
|
3588
|
-
export { BarcodeDetectorService, BatteryService, BroadcastChannelService, BrowserApiBaseService, BrowserCapabilityService, BrowserSupportUtil, CameraService, ClipboardService, ConnectionRegistryBaseService, CredentialManagementService, EyeDropperService, FileSystemAccessService, FullscreenService, GamepadService, GeolocationService, IdleDetectorService, IntersectionObserverService, MediaDevicesService, MediaRecorderService, MutationObserverService, NetworkInformationService, NotificationService, PageVisibilityService, PaymentRequestService, PerformanceObserverService,
|
|
3632
|
+
export { BROWSER_API_LOGGER, BarcodeDetectorService, BatteryService, BroadcastChannelService, BrowserApiBaseService, BrowserCapabilityService, BrowserSupportUtil, CameraService, ClipboardService, ConnectionRegistryBaseService, CredentialManagementService, EyeDropperService, FileSystemAccessService, FullscreenService, GamepadService, GeolocationService, IdleDetectorService, IntersectionObserverService, MediaDevicesService, MediaRecorderService, MutationObserverService, NetworkInformationService, NotificationService, PageVisibilityService, PaymentRequestService, PerformanceObserverService, PermissionsService, ResizeObserverService, ScreenOrientationService, ScreenWakeLockService, ServerSentEventsService, SpeechSynthesisService, VibrationService, WebAudioService, WebBluetoothService, WebNfcService, WebShareService, WebSocketService, WebStorageService, WebUsbService, WebWorkerService, permissionGuard as createPermissionGuard, defaultBrowserWebApisConfig, injectGamepad, injectIdleDetector, injectIntersectionObserver, injectMutationObserver, injectNetworkInformation, injectPageVisibility, injectPerformanceObserver, injectResizeObserver, injectScreenOrientation, permissionGuard, provideBarcodeDetector, provideBattery, provideBroadcastChannel, provideBrowserWebApis, provideCamera, provideClipboard, provideCommunicationApis, provideCredentialManagement, provideEyeDropper, provideFileSystemAccess, provideFullscreen, provideGamepad, provideGeolocation, provideIdleDetector, provideIntersectionObserver, provideLocationApis, provideMediaApis, provideMediaDevices, provideMediaRecorder, provideMutationObserver, provideNetworkInformation, provideNotifications, providePageVisibility, providePaymentRequest, providePerformanceObserver, providePermissions, provideResizeObserver, provideScreenOrientation, provideScreenWakeLock, provideServerSentEvents, provideSpeechSynthesis, provideStorageApis, provideVibration, provideWebAudio, provideWebBluetooth, provideWebNfc, provideWebShare, provideWebSocket, provideWebStorage, provideWebUsb, provideWebWorker, version };
|