@angular-helpers/browser-web-apis 21.0.1 → 21.0.2
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.
|
@@ -0,0 +1,668 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { Injectable, inject, DestroyRef, PLATFORM_ID } from '@angular/core';
|
|
3
|
+
import { isPlatformBrowser, isPlatformServer } from '@angular/common';
|
|
4
|
+
import { Observable } from 'rxjs';
|
|
5
|
+
|
|
6
|
+
class PermissionsService {
|
|
7
|
+
async query(descriptor) {
|
|
8
|
+
if (!this.isSupported()) {
|
|
9
|
+
throw new Error('Permissions API not supported');
|
|
10
|
+
}
|
|
11
|
+
try {
|
|
12
|
+
return await navigator.permissions.query(descriptor);
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
console.error('Error querying permission:', error);
|
|
16
|
+
throw error;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
isSupported() {
|
|
20
|
+
return typeof navigator !== 'undefined' && 'permissions' in navigator;
|
|
21
|
+
}
|
|
22
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: PermissionsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
23
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: PermissionsService });
|
|
24
|
+
}
|
|
25
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: PermissionsService, decorators: [{
|
|
26
|
+
type: Injectable
|
|
27
|
+
}] });
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Base class for all Browser Web API services
|
|
31
|
+
* Provides common functionality for:
|
|
32
|
+
* - Support checking
|
|
33
|
+
* - Permission management
|
|
34
|
+
* - Error handling
|
|
35
|
+
* - Lifecycle management with destroyRef
|
|
36
|
+
* - Logging
|
|
37
|
+
*/
|
|
38
|
+
class BrowserApiBaseService {
|
|
39
|
+
permissionsService = inject(PermissionsService);
|
|
40
|
+
destroyRef = inject(DestroyRef);
|
|
41
|
+
platformId = inject(PLATFORM_ID);
|
|
42
|
+
/**
|
|
43
|
+
* Check if running in browser environment using Angular's platform detection
|
|
44
|
+
*/
|
|
45
|
+
isBrowserEnvironment() {
|
|
46
|
+
return isPlatformBrowser(this.platformId);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Check if running in server environment using Angular's platform detection
|
|
50
|
+
*/
|
|
51
|
+
isServerEnvironment() {
|
|
52
|
+
return isPlatformServer(this.platformId);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Request a permission
|
|
56
|
+
*/
|
|
57
|
+
async requestPermission(permission) {
|
|
58
|
+
if (this.isServerEnvironment()) {
|
|
59
|
+
throw new Error(`${this.getApiName()} API not available in server environment`);
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
const status = await this.permissionsService.query({ name: permission });
|
|
63
|
+
return status.state === 'granted';
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
console.error(`[${this.getApiName()}] Error requesting permission for ${permission}:`, error);
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: BrowserApiBaseService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
71
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: BrowserApiBaseService });
|
|
72
|
+
}
|
|
73
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: BrowserApiBaseService, decorators: [{
|
|
74
|
+
type: Injectable
|
|
75
|
+
}] });
|
|
76
|
+
|
|
77
|
+
class CameraService extends BrowserApiBaseService {
|
|
78
|
+
currentStream = null;
|
|
79
|
+
createError(message, cause) {
|
|
80
|
+
const error = new Error(message);
|
|
81
|
+
error.cause = cause;
|
|
82
|
+
return error;
|
|
83
|
+
}
|
|
84
|
+
getApiName() {
|
|
85
|
+
return 'camera';
|
|
86
|
+
}
|
|
87
|
+
ensureCameraSupport() {
|
|
88
|
+
if (!('mediaDevices' in navigator) || !('getUserMedia' in navigator.mediaDevices)) {
|
|
89
|
+
throw new Error('Camera API not supported in this browser');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
async startCamera(constraints) {
|
|
93
|
+
this.ensureCameraSupport();
|
|
94
|
+
if (this.currentStream) {
|
|
95
|
+
this.stopCamera();
|
|
96
|
+
}
|
|
97
|
+
const permissionStatus = await this.permissionsService.query({ name: 'camera' });
|
|
98
|
+
if (permissionStatus.state !== 'granted') {
|
|
99
|
+
throw new Error('Camera permission required. Please grant camera access and try again.');
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
const streamConstraints = constraints || {
|
|
103
|
+
video: {
|
|
104
|
+
width: { ideal: 1280 },
|
|
105
|
+
height: { ideal: 720 },
|
|
106
|
+
facingMode: 'user'
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
this.currentStream = await navigator.mediaDevices.getUserMedia(streamConstraints);
|
|
110
|
+
return this.currentStream;
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
console.error('[CameraService] Error starting camera:', error);
|
|
114
|
+
if (error instanceof Error && error.name === 'NotAllowedError') {
|
|
115
|
+
throw this.createError('Camera permission denied by user. Please allow camera access in your browser settings and refresh the page.', error);
|
|
116
|
+
}
|
|
117
|
+
else if (error instanceof Error && error.name === 'NotFoundError') {
|
|
118
|
+
throw this.createError('No camera device found. Please connect a camera and try again.', error);
|
|
119
|
+
}
|
|
120
|
+
else if (error instanceof Error && error.name === 'NotReadableError') {
|
|
121
|
+
throw this.createError('Camera is already in use by another application. Please close other applications using the camera and try again.', error);
|
|
122
|
+
}
|
|
123
|
+
else if (error instanceof Error && error.name === 'OverconstrainedError') {
|
|
124
|
+
throw this.createError('Camera constraints cannot be satisfied. Try with different camera settings.', error);
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
|
|
128
|
+
throw this.createError(`Camera error: ${errorMessage}`, error);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
stopCamera() {
|
|
133
|
+
if (this.currentStream) {
|
|
134
|
+
this.currentStream.getTracks().forEach((track) => {
|
|
135
|
+
track.stop();
|
|
136
|
+
});
|
|
137
|
+
this.currentStream = null;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
async switchCamera(deviceId, constraints = {
|
|
141
|
+
video: {
|
|
142
|
+
width: { ideal: 1280 },
|
|
143
|
+
height: { ideal: 720 }
|
|
144
|
+
}
|
|
145
|
+
}) {
|
|
146
|
+
this.stopCamera();
|
|
147
|
+
const finalConstraints = {
|
|
148
|
+
video: constraints.video && typeof constraints.video === 'object'
|
|
149
|
+
? { ...constraints.video, deviceId: { exact: deviceId } }
|
|
150
|
+
: { deviceId: { exact: deviceId } }
|
|
151
|
+
};
|
|
152
|
+
return this.startCamera(finalConstraints);
|
|
153
|
+
}
|
|
154
|
+
async getCameraCapabilities(deviceId) {
|
|
155
|
+
this.ensureCameraSupport();
|
|
156
|
+
try {
|
|
157
|
+
const stream = await navigator.mediaDevices.getUserMedia({
|
|
158
|
+
video: { deviceId: { exact: deviceId } }
|
|
159
|
+
});
|
|
160
|
+
const videoTrack = stream.getVideoTracks()[0];
|
|
161
|
+
const capabilities = videoTrack.getCapabilities();
|
|
162
|
+
// Clean up the stream
|
|
163
|
+
stream.getTracks().forEach((track) => track.stop());
|
|
164
|
+
return capabilities || null;
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
console.error('[CameraService] Error getting camera capabilities:', error);
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
getCurrentStream() {
|
|
172
|
+
return this.currentStream;
|
|
173
|
+
}
|
|
174
|
+
isStreaming() {
|
|
175
|
+
return this.currentStream !== null;
|
|
176
|
+
}
|
|
177
|
+
async getVideoInputDevices() {
|
|
178
|
+
this.ensureCameraSupport();
|
|
179
|
+
try {
|
|
180
|
+
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
181
|
+
return devices.filter(device => device.kind === 'videoinput');
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
console.error('[CameraService] Error enumerating video devices:', error);
|
|
185
|
+
throw this.createError('Failed to enumerate video devices', error);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
// Direct access to native camera API
|
|
189
|
+
getNativeMediaDevices() {
|
|
190
|
+
this.ensureCameraSupport();
|
|
191
|
+
return navigator.mediaDevices;
|
|
192
|
+
}
|
|
193
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: CameraService, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
194
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: CameraService });
|
|
195
|
+
}
|
|
196
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: CameraService, decorators: [{
|
|
197
|
+
type: Injectable
|
|
198
|
+
}] });
|
|
199
|
+
|
|
200
|
+
class GeolocationService extends BrowserApiBaseService {
|
|
201
|
+
getApiName() {
|
|
202
|
+
return 'geolocation';
|
|
203
|
+
}
|
|
204
|
+
ensureGeolocationSupport() {
|
|
205
|
+
if (!('geolocation' in navigator)) {
|
|
206
|
+
throw new Error('Geolocation API not supported in this browser');
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
getCurrentPosition(options) {
|
|
210
|
+
this.ensureGeolocationSupport();
|
|
211
|
+
return new Promise((resolve, reject) => {
|
|
212
|
+
navigator.geolocation.getCurrentPosition((position) => resolve(position), (error) => {
|
|
213
|
+
console.error('[GeolocationService] Error getting position:', error);
|
|
214
|
+
reject(error);
|
|
215
|
+
}, options);
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
watchPosition(options) {
|
|
219
|
+
this.ensureGeolocationSupport();
|
|
220
|
+
return new Observable((observer) => {
|
|
221
|
+
const watchId = navigator.geolocation.watchPosition((position) => observer.next(position), (error) => {
|
|
222
|
+
console.error('[GeolocationService] Error watching position:', error);
|
|
223
|
+
observer.error(error);
|
|
224
|
+
}, options);
|
|
225
|
+
return () => {
|
|
226
|
+
navigator.geolocation.clearWatch(watchId);
|
|
227
|
+
};
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
clearWatch(watchId) {
|
|
231
|
+
navigator.geolocation.clearWatch(watchId);
|
|
232
|
+
}
|
|
233
|
+
// Direct access to native geolocation API
|
|
234
|
+
getNativeGeolocation() {
|
|
235
|
+
this.ensureGeolocationSupport();
|
|
236
|
+
return navigator.geolocation;
|
|
237
|
+
}
|
|
238
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: GeolocationService, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
239
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: GeolocationService });
|
|
240
|
+
}
|
|
241
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: GeolocationService, decorators: [{
|
|
242
|
+
type: Injectable
|
|
243
|
+
}] });
|
|
244
|
+
|
|
245
|
+
class MediaDevicesService extends BrowserApiBaseService {
|
|
246
|
+
createError(message, cause) {
|
|
247
|
+
const error = new Error(message);
|
|
248
|
+
error.cause = cause;
|
|
249
|
+
return error;
|
|
250
|
+
}
|
|
251
|
+
getApiName() {
|
|
252
|
+
return 'media-devices';
|
|
253
|
+
}
|
|
254
|
+
ensureMediaDevicesSupport() {
|
|
255
|
+
if (!('mediaDevices' in navigator)) {
|
|
256
|
+
throw new Error('MediaDevices API not supported in this browser');
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
async getDevices() {
|
|
260
|
+
this.ensureMediaDevicesSupport();
|
|
261
|
+
try {
|
|
262
|
+
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
263
|
+
return devices;
|
|
264
|
+
}
|
|
265
|
+
catch (error) {
|
|
266
|
+
console.error('[MediaDevicesService] Error enumerating devices:', error);
|
|
267
|
+
throw this.createError('Failed to enumerate media devices', error);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
async getUserMedia(constraints) {
|
|
271
|
+
this.ensureMediaDevicesSupport();
|
|
272
|
+
try {
|
|
273
|
+
const defaultConstraints = {
|
|
274
|
+
video: true,
|
|
275
|
+
audio: true
|
|
276
|
+
};
|
|
277
|
+
const finalConstraints = constraints || defaultConstraints;
|
|
278
|
+
return await navigator.mediaDevices.getUserMedia(finalConstraints);
|
|
279
|
+
}
|
|
280
|
+
catch (error) {
|
|
281
|
+
console.error('[MediaDevicesService] Error getting user media:', error);
|
|
282
|
+
throw this.handleMediaError(error);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
async getDisplayMedia(constraints) {
|
|
286
|
+
this.ensureMediaDevicesSupport();
|
|
287
|
+
if (!('getDisplayMedia' in navigator.mediaDevices)) {
|
|
288
|
+
throw new Error('Display media API not supported in this browser');
|
|
289
|
+
}
|
|
290
|
+
try {
|
|
291
|
+
const defaultConstraints = {
|
|
292
|
+
video: true,
|
|
293
|
+
audio: false
|
|
294
|
+
};
|
|
295
|
+
const finalConstraints = constraints || defaultConstraints;
|
|
296
|
+
return await navigator.mediaDevices.getDisplayMedia(finalConstraints);
|
|
297
|
+
}
|
|
298
|
+
catch (error) {
|
|
299
|
+
console.error('[MediaDevicesService] Error getting display media:', error);
|
|
300
|
+
throw this.createError('Failed to get display media', error);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
watchDeviceChanges() {
|
|
304
|
+
this.ensureMediaDevicesSupport();
|
|
305
|
+
return new Observable((observer) => {
|
|
306
|
+
const handleDeviceChange = async () => {
|
|
307
|
+
try {
|
|
308
|
+
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
309
|
+
observer.next(devices);
|
|
310
|
+
}
|
|
311
|
+
catch (error) {
|
|
312
|
+
console.error('[MediaDevicesService] Error handling device change:', error);
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
// Listen for device changes
|
|
316
|
+
navigator.mediaDevices.addEventListener('devicechange', handleDeviceChange);
|
|
317
|
+
// Get initial devices
|
|
318
|
+
handleDeviceChange();
|
|
319
|
+
return () => {
|
|
320
|
+
navigator.mediaDevices.removeEventListener('devicechange', handleDeviceChange);
|
|
321
|
+
};
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
getVideoInputDevices() {
|
|
325
|
+
return this.getDevicesByKind('videoinput');
|
|
326
|
+
}
|
|
327
|
+
getAudioInputDevices() {
|
|
328
|
+
return this.getDevicesByKind('audioinput');
|
|
329
|
+
}
|
|
330
|
+
getAudioOutputDevices() {
|
|
331
|
+
return this.getDevicesByKind('audiooutput');
|
|
332
|
+
}
|
|
333
|
+
async getDevicesByKind(kind) {
|
|
334
|
+
const devices = await this.getDevices();
|
|
335
|
+
return devices.filter(device => device.kind === kind);
|
|
336
|
+
}
|
|
337
|
+
handleMediaError(error) {
|
|
338
|
+
let message;
|
|
339
|
+
if (error instanceof Error) {
|
|
340
|
+
switch (error.name) {
|
|
341
|
+
case 'NotAllowedError':
|
|
342
|
+
message = 'Permission denied by user';
|
|
343
|
+
break;
|
|
344
|
+
case 'NotFoundError':
|
|
345
|
+
message = 'No media device found';
|
|
346
|
+
break;
|
|
347
|
+
case 'NotReadableError':
|
|
348
|
+
message = 'Media device is already in use';
|
|
349
|
+
break;
|
|
350
|
+
case 'OverconstrainedError':
|
|
351
|
+
message = 'Media constraints cannot be satisfied';
|
|
352
|
+
break;
|
|
353
|
+
case 'TypeError':
|
|
354
|
+
message = 'Invalid media constraints provided';
|
|
355
|
+
break;
|
|
356
|
+
default:
|
|
357
|
+
message = `Media error: ${error.message}`;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
message = 'Unknown media error occurred';
|
|
362
|
+
}
|
|
363
|
+
return this.createError(message, error);
|
|
364
|
+
}
|
|
365
|
+
// Direct access to native media devices API
|
|
366
|
+
getNativeMediaDevices() {
|
|
367
|
+
this.ensureMediaDevicesSupport();
|
|
368
|
+
return navigator.mediaDevices;
|
|
369
|
+
}
|
|
370
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MediaDevicesService, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
371
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MediaDevicesService });
|
|
372
|
+
}
|
|
373
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MediaDevicesService, decorators: [{
|
|
374
|
+
type: Injectable
|
|
375
|
+
}] });
|
|
376
|
+
|
|
377
|
+
class NotificationService extends BrowserApiBaseService {
|
|
378
|
+
getApiName() {
|
|
379
|
+
return 'notifications';
|
|
380
|
+
}
|
|
381
|
+
async showNotification(title, options) {
|
|
382
|
+
if (!('Notification' in window)) {
|
|
383
|
+
throw new Error('Notification API not supported in this browser');
|
|
384
|
+
}
|
|
385
|
+
const permissionStatus = await this.permissionsService.query({ name: 'notifications' });
|
|
386
|
+
if (permissionStatus.state !== 'granted') {
|
|
387
|
+
throw new Error('Notification permission required. Please grant notification access and try again.');
|
|
388
|
+
}
|
|
389
|
+
try {
|
|
390
|
+
return new Notification(title, options);
|
|
391
|
+
}
|
|
392
|
+
catch (error) {
|
|
393
|
+
console.error('[NotificationService] Error showing notification:', error);
|
|
394
|
+
throw error;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: NotificationService, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
398
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: NotificationService });
|
|
399
|
+
}
|
|
400
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: NotificationService, decorators: [{
|
|
401
|
+
type: Injectable
|
|
402
|
+
}] });
|
|
403
|
+
|
|
404
|
+
class ClipboardService extends BrowserApiBaseService {
|
|
405
|
+
getApiName() {
|
|
406
|
+
return 'clipboard';
|
|
407
|
+
}
|
|
408
|
+
async ensureClipboardPermission(action) {
|
|
409
|
+
if (!('clipboard' in navigator)) {
|
|
410
|
+
throw new Error('Clipboard API not supported in this browser');
|
|
411
|
+
}
|
|
412
|
+
const permissionStatus = await this.permissionsService.query({
|
|
413
|
+
name: `clipboard-${action}`
|
|
414
|
+
});
|
|
415
|
+
if (permissionStatus.state !== 'granted') {
|
|
416
|
+
throw new Error(`Clipboard ${action} permission required. Please grant clipboard access and try again.`);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
async writeText(text) {
|
|
420
|
+
await this.ensureClipboardPermission('write');
|
|
421
|
+
try {
|
|
422
|
+
await navigator.clipboard.writeText(text);
|
|
423
|
+
}
|
|
424
|
+
catch (error) {
|
|
425
|
+
console.error('[ClipboardService] Error writing to clipboard:', error);
|
|
426
|
+
throw error;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
async readText() {
|
|
430
|
+
await this.ensureClipboardPermission('read');
|
|
431
|
+
try {
|
|
432
|
+
return await navigator.clipboard.readText();
|
|
433
|
+
}
|
|
434
|
+
catch (error) {
|
|
435
|
+
console.error('[ClipboardService] Error reading from clipboard:', error);
|
|
436
|
+
throw error;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
async writeTextSecure(text) {
|
|
440
|
+
await this.ensureClipboardPermission('write');
|
|
441
|
+
try {
|
|
442
|
+
await navigator.clipboard.writeText(text);
|
|
443
|
+
}
|
|
444
|
+
catch (error) {
|
|
445
|
+
console.error('[ClipboardService] Error writing to clipboard:', error);
|
|
446
|
+
throw error;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ClipboardService, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
450
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ClipboardService });
|
|
451
|
+
}
|
|
452
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ClipboardService, decorators: [{
|
|
453
|
+
type: Injectable
|
|
454
|
+
}] });
|
|
455
|
+
|
|
456
|
+
const BROWSER_CAPABILITIES = [
|
|
457
|
+
{ id: 'permissions', label: 'Permissions API', requiresSecureContext: false },
|
|
458
|
+
{ id: 'geolocation', label: 'Geolocation API', requiresSecureContext: true },
|
|
459
|
+
{ id: 'clipboard', label: 'Clipboard API', requiresSecureContext: true },
|
|
460
|
+
{ id: 'notification', label: 'Notification API', requiresSecureContext: true },
|
|
461
|
+
{ id: 'mediaDevices', label: 'MediaDevices API', requiresSecureContext: true },
|
|
462
|
+
{ id: 'camera', label: 'Camera API', requiresSecureContext: true },
|
|
463
|
+
{ id: 'webWorker', label: 'Web Worker API', requiresSecureContext: false },
|
|
464
|
+
{ id: 'regexSecurity', label: 'Regex Security', requiresSecureContext: false },
|
|
465
|
+
{ id: 'webStorage', label: 'Web Storage', requiresSecureContext: false },
|
|
466
|
+
{ id: 'webShare', label: 'Web Share', requiresSecureContext: true },
|
|
467
|
+
{ id: 'battery', label: 'Battery API', requiresSecureContext: false },
|
|
468
|
+
{ id: 'webSocket', label: 'WebSocket API', requiresSecureContext: false }
|
|
469
|
+
];
|
|
470
|
+
class BrowserCapabilityService {
|
|
471
|
+
getCapabilities() {
|
|
472
|
+
return BROWSER_CAPABILITIES;
|
|
473
|
+
}
|
|
474
|
+
isSecureContext() {
|
|
475
|
+
return typeof window !== 'undefined' && window.isSecureContext;
|
|
476
|
+
}
|
|
477
|
+
isSupported(capability) {
|
|
478
|
+
switch (capability) {
|
|
479
|
+
case 'permissions':
|
|
480
|
+
return typeof navigator !== 'undefined' && 'permissions' in navigator;
|
|
481
|
+
case 'geolocation':
|
|
482
|
+
return typeof navigator !== 'undefined' && 'geolocation' in navigator;
|
|
483
|
+
case 'clipboard':
|
|
484
|
+
return typeof navigator !== 'undefined' && 'clipboard' in navigator;
|
|
485
|
+
case 'notification':
|
|
486
|
+
return typeof window !== 'undefined' && 'Notification' in window;
|
|
487
|
+
case 'mediaDevices':
|
|
488
|
+
case 'camera':
|
|
489
|
+
return typeof navigator !== 'undefined' && 'mediaDevices' in navigator;
|
|
490
|
+
case 'webWorker':
|
|
491
|
+
case 'regexSecurity':
|
|
492
|
+
return typeof Worker !== 'undefined';
|
|
493
|
+
case 'webStorage':
|
|
494
|
+
return typeof Storage !== 'undefined';
|
|
495
|
+
case 'webShare':
|
|
496
|
+
return typeof navigator !== 'undefined' && 'share' in navigator;
|
|
497
|
+
case 'battery':
|
|
498
|
+
return typeof navigator !== 'undefined' && 'getBattery' in navigator;
|
|
499
|
+
case 'webSocket':
|
|
500
|
+
return typeof WebSocket !== 'undefined';
|
|
501
|
+
default:
|
|
502
|
+
return false;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
getAllStatuses() {
|
|
506
|
+
const secureContext = this.isSecureContext();
|
|
507
|
+
return this.getCapabilities().map((capability) => ({
|
|
508
|
+
id: capability.id,
|
|
509
|
+
label: capability.label,
|
|
510
|
+
supported: this.isSupported(capability.id),
|
|
511
|
+
secureContext,
|
|
512
|
+
requiresSecureContext: capability.requiresSecureContext
|
|
513
|
+
}));
|
|
514
|
+
}
|
|
515
|
+
async getPermissionState(permission) {
|
|
516
|
+
if (typeof navigator === 'undefined' || !('permissions' in navigator)) {
|
|
517
|
+
return 'unknown';
|
|
518
|
+
}
|
|
519
|
+
try {
|
|
520
|
+
const status = await navigator.permissions.query({ name: permission });
|
|
521
|
+
return status.state;
|
|
522
|
+
}
|
|
523
|
+
catch {
|
|
524
|
+
return 'unknown';
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: BrowserCapabilityService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
528
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: BrowserCapabilityService, providedIn: 'root' });
|
|
529
|
+
}
|
|
530
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: BrowserCapabilityService, decorators: [{
|
|
531
|
+
type: Injectable,
|
|
532
|
+
args: [{ providedIn: 'root' }]
|
|
533
|
+
}] });
|
|
534
|
+
|
|
535
|
+
class BrowserSupportUtil {
|
|
536
|
+
static isSupported(feature) {
|
|
537
|
+
if (typeof window === 'undefined' || typeof navigator === 'undefined') {
|
|
538
|
+
return false;
|
|
539
|
+
}
|
|
540
|
+
switch (feature) {
|
|
541
|
+
case 'permissions':
|
|
542
|
+
return 'permissions' in navigator;
|
|
543
|
+
case 'camera':
|
|
544
|
+
return 'mediaDevices' in navigator && 'getUserMedia' in navigator.mediaDevices;
|
|
545
|
+
case 'microphone':
|
|
546
|
+
return 'mediaDevices' in navigator && 'getUserMedia' in navigator.mediaDevices;
|
|
547
|
+
case 'geolocation':
|
|
548
|
+
return 'geolocation' in navigator;
|
|
549
|
+
case 'notifications':
|
|
550
|
+
return 'Notification' in window;
|
|
551
|
+
case 'clipboard':
|
|
552
|
+
return 'clipboard' in navigator;
|
|
553
|
+
case 'clipboard-read':
|
|
554
|
+
return 'clipboard' in navigator && 'readText' in navigator.clipboard;
|
|
555
|
+
case 'clipboard-write':
|
|
556
|
+
return 'clipboard' in navigator && 'writeText' in navigator.clipboard;
|
|
557
|
+
case 'persistent-storage':
|
|
558
|
+
return 'storage' in navigator && 'persist' in navigator.storage;
|
|
559
|
+
default:
|
|
560
|
+
return false;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
static getUnsupportedFeatures() {
|
|
564
|
+
const features = [
|
|
565
|
+
'permissions',
|
|
566
|
+
'camera',
|
|
567
|
+
'microphone',
|
|
568
|
+
'geolocation',
|
|
569
|
+
'notifications',
|
|
570
|
+
'clipboard',
|
|
571
|
+
'clipboard-read',
|
|
572
|
+
'clipboard-write',
|
|
573
|
+
'persistent-storage'
|
|
574
|
+
];
|
|
575
|
+
return features.filter(feature => !this.isSupported(feature));
|
|
576
|
+
}
|
|
577
|
+
static isSecureContext() {
|
|
578
|
+
return typeof window !== 'undefined' ? window.isSecureContext : false;
|
|
579
|
+
}
|
|
580
|
+
static getUserAgent() {
|
|
581
|
+
return typeof navigator !== 'undefined' ? navigator.userAgent : '';
|
|
582
|
+
}
|
|
583
|
+
static isMobile() {
|
|
584
|
+
const userAgent = this.getUserAgent().toLowerCase();
|
|
585
|
+
return /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(userAgent);
|
|
586
|
+
}
|
|
587
|
+
static isDesktop() {
|
|
588
|
+
return !this.isMobile();
|
|
589
|
+
}
|
|
590
|
+
static getBrowserInfo() {
|
|
591
|
+
const userAgent = this.getUserAgent();
|
|
592
|
+
return {
|
|
593
|
+
name: this.getBrowserName(userAgent),
|
|
594
|
+
version: this.getBrowserVersion(userAgent),
|
|
595
|
+
isChrome: /chrome/.test(userAgent) && !/edge/.test(userAgent),
|
|
596
|
+
isFirefox: /firefox/.test(userAgent),
|
|
597
|
+
isSafari: /safari/.test(userAgent) && !/chrome/.test(userAgent),
|
|
598
|
+
isEdge: /edge/.test(userAgent) || /edg/.test(userAgent)
|
|
599
|
+
};
|
|
600
|
+
}
|
|
601
|
+
static getBrowserName(userAgent) {
|
|
602
|
+
if (/chrome/.test(userAgent) && !/edge/.test(userAgent))
|
|
603
|
+
return 'Chrome';
|
|
604
|
+
if (/firefox/.test(userAgent))
|
|
605
|
+
return 'Firefox';
|
|
606
|
+
if (/safari/.test(userAgent) && !/chrome/.test(userAgent))
|
|
607
|
+
return 'Safari';
|
|
608
|
+
if (/edge/.test(userAgent) || /edg/.test(userAgent))
|
|
609
|
+
return 'Edge';
|
|
610
|
+
return 'Unknown';
|
|
611
|
+
}
|
|
612
|
+
static getBrowserVersion(userAgent) {
|
|
613
|
+
const match = userAgent.match(/(chrome|firefox|safari|edge|edg)\/(\d+)/i);
|
|
614
|
+
return match ? match[2] : 'Unknown';
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
class PermissionGuard {
|
|
619
|
+
permissionsService;
|
|
620
|
+
router;
|
|
621
|
+
constructor(permissionsService, router) {
|
|
622
|
+
this.permissionsService = permissionsService;
|
|
623
|
+
this.router = router;
|
|
624
|
+
}
|
|
625
|
+
canActivate(route) {
|
|
626
|
+
const permission = route.data?.['permission'];
|
|
627
|
+
if (!permission) {
|
|
628
|
+
return Promise.resolve(true);
|
|
629
|
+
}
|
|
630
|
+
return this.checkPermission(permission);
|
|
631
|
+
}
|
|
632
|
+
async checkPermission(permission) {
|
|
633
|
+
try {
|
|
634
|
+
const status = await this.permissionsService.query({ name: permission });
|
|
635
|
+
if (status.state !== 'granted') {
|
|
636
|
+
this.router.navigate(['/permission-denied'], {
|
|
637
|
+
queryParams: { permission }
|
|
638
|
+
});
|
|
639
|
+
return false;
|
|
640
|
+
}
|
|
641
|
+
return true;
|
|
642
|
+
}
|
|
643
|
+
catch (error) {
|
|
644
|
+
console.error('Permission guard error:', error);
|
|
645
|
+
this.router.navigate(['/permission-denied'], {
|
|
646
|
+
queryParams: { permission }
|
|
647
|
+
});
|
|
648
|
+
return false;
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
function createPermissionGuard(permission) {
|
|
653
|
+
return {
|
|
654
|
+
canActivate: [PermissionGuard],
|
|
655
|
+
data: { permission }
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
// Browser Web APIs Services
|
|
660
|
+
// Version
|
|
661
|
+
const version = '0.1.0';
|
|
662
|
+
|
|
663
|
+
/**
|
|
664
|
+
* Generated bundle index. Do not edit.
|
|
665
|
+
*/
|
|
666
|
+
|
|
667
|
+
export { BrowserCapabilityService, BrowserSupportUtil, CameraService, ClipboardService, GeolocationService, MediaDevicesService, NotificationService, PermissionGuard, PermissionsService, createPermissionGuard, version };
|
|
668
|
+
//# sourceMappingURL=angular-helpers-browser-web-apis.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"angular-helpers-browser-web-apis.mjs","sources":["../../../packages/browser-web-apis/src/services/permissions.service.ts","../../../packages/browser-web-apis/src/services/base/browser-api-base.service.ts","../../../packages/browser-web-apis/src/services/camera.service.ts","../../../packages/browser-web-apis/src/services/geolocation.service.ts","../../../packages/browser-web-apis/src/services/media-devices.service.ts","../../../packages/browser-web-apis/src/services/notification.service.ts","../../../packages/browser-web-apis/src/services/clipboard.service.ts","../../../packages/browser-web-apis/src/services/browser-capability.service.ts","../../../packages/browser-web-apis/src/utils/browser-support.util.ts","../../../packages/browser-web-apis/src/guards/permission.guard.ts","../../../packages/browser-web-apis/src/public-api.ts","../../../packages/browser-web-apis/src/angular-helpers-browser-web-apis.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport { \n BrowserPermissions \n} from '../interfaces/permissions.interface';\n\n@Injectable()\nexport class PermissionsService implements BrowserPermissions {\n\n async query(descriptor: PermissionDescriptor): Promise<PermissionStatus> {\n if (!this.isSupported()) {\n throw new Error('Permissions API not supported');\n }\n\n try {\n return await navigator.permissions.query(descriptor as PermissionDescriptor);\n } catch (error) {\n console.error('Error querying permission:', error);\n throw error;\n }\n }\n\n isSupported(): boolean {\n return typeof navigator !== 'undefined' && 'permissions' in navigator;\n }\n}\n","import { Injectable, inject, DestroyRef, PLATFORM_ID } from '@angular/core';\nimport { isPlatformBrowser, isPlatformServer } from '@angular/common';\nimport { PermissionsService } from '../permissions.service';\nimport { PermissionNameExt } from '../../public-api';\n\n/**\n * Base class for all Browser Web API services\n * Provides common functionality for:\n * - Support checking\n * - Permission management\n * - Error handling\n * - Lifecycle management with destroyRef\n * - Logging\n */\n@Injectable()\nexport abstract class BrowserApiBaseService {\n protected permissionsService = inject(PermissionsService);\n protected destroyRef = inject(DestroyRef);\n protected platformId = inject(PLATFORM_ID);\n \n /**\n * Abstract method that must be implemented by child services\n * Returns the API name for support checking\n */\n protected abstract getApiName(): string;\n\n /**\n * Check if running in browser environment using Angular's platform detection\n */\n protected isBrowserEnvironment(): boolean {\n return isPlatformBrowser(this.platformId);\n }\n\n /**\n * Check if running in server environment using Angular's platform detection\n */\n protected isServerEnvironment(): boolean {\n return isPlatformServer(this.platformId);\n }\n \n /**\n * Request a permission\n */\n protected async requestPermission(permission: PermissionNameExt): Promise<boolean> {\n if (this.isServerEnvironment()) {\n throw new Error(`${this.getApiName()} API not available in server environment`);\n }\n \n try {\n const status = await this.permissionsService.query({ name: permission as PermissionName });\n return status.state === 'granted';\n } catch (error) {\n console.error(`[${this.getApiName()}] Error requesting permission for ${permission}:`, error);\n return false;\n }\n }\n \n}\n","import { Injectable } from '@angular/core';\nimport { BrowserApiBaseService } from './base/browser-api-base.service';\n\n@Injectable()\nexport class CameraService extends BrowserApiBaseService {\n private currentStream: MediaStream | null = null;\n\n private createError(message: string, cause: unknown): Error {\n const error = new Error(message) as Error & { cause?: unknown };\n error.cause = cause;\n return error;\n }\n\n protected override getApiName(): string {\n return 'camera';\n }\n\n private ensureCameraSupport(): void {\n if (!('mediaDevices' in navigator) || !('getUserMedia' in navigator.mediaDevices)) {\n throw new Error('Camera API not supported in this browser');\n }\n }\n\n async startCamera(constraints?: MediaStreamConstraints): Promise<MediaStream> {\n this.ensureCameraSupport();\n\n if (this.currentStream) {\n this.stopCamera();\n }\n\n const permissionStatus = await this.permissionsService.query({ name: 'camera' });\n if (permissionStatus.state !== 'granted') {\n throw new Error('Camera permission required. Please grant camera access and try again.');\n }\n\n try {\n const streamConstraints: MediaStreamConstraints = constraints || {\n video: {\n width: { ideal: 1280 },\n height: { ideal: 720 },\n facingMode: 'user'\n }\n };\n\n this.currentStream = await navigator.mediaDevices.getUserMedia(streamConstraints);\n return this.currentStream;\n } catch (error: unknown) {\n console.error('[CameraService] Error starting camera:', error);\n \n if (error instanceof Error && error.name === 'NotAllowedError') {\n throw this.createError('Camera permission denied by user. Please allow camera access in your browser settings and refresh the page.', error);\n } else if (error instanceof Error && error.name === 'NotFoundError') {\n throw this.createError('No camera device found. Please connect a camera and try again.', error);\n } else if (error instanceof Error && error.name === 'NotReadableError') {\n throw this.createError('Camera is already in use by another application. Please close other applications using the camera and try again.', error);\n } else if (error instanceof Error && error.name === 'OverconstrainedError') {\n throw this.createError('Camera constraints cannot be satisfied. Try with different camera settings.', error);\n } else {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';\n throw this.createError(`Camera error: ${errorMessage}`, error);\n }\n }\n }\n\n stopCamera(): void {\n if (this.currentStream) {\n this.currentStream.getTracks().forEach((track: MediaStreamTrack) => {\n track.stop();\n });\n this.currentStream = null;\n }\n }\n\n async switchCamera(deviceId: string, constraints: MediaStreamConstraints = {\n video: {\n width: { ideal: 1280 },\n height: { ideal: 720 }\n }\n }): Promise<MediaStream> {\n this.stopCamera();\n\n const finalConstraints: MediaStreamConstraints = {\n video: constraints.video && typeof constraints.video === 'object' \n ? { ...constraints.video, deviceId: { exact: deviceId } }\n : { deviceId: { exact: deviceId } }\n };\n\n return this.startCamera(finalConstraints);\n }\n\n async getCameraCapabilities(deviceId: string): Promise<MediaTrackCapabilities | null> {\n this.ensureCameraSupport();\n\n try {\n const stream = await navigator.mediaDevices.getUserMedia({\n video: { deviceId: { exact: deviceId } }\n });\n\n const videoTrack = stream.getVideoTracks()[0];\n const capabilities = videoTrack.getCapabilities();\n\n // Clean up the stream\n stream.getTracks().forEach((track: MediaStreamTrack) => track.stop());\n\n return capabilities || null;\n } catch (error) {\n console.error('[CameraService] Error getting camera capabilities:', error);\n return null;\n }\n }\n\n getCurrentStream(): MediaStream | null {\n return this.currentStream;\n }\n\n isStreaming(): boolean {\n return this.currentStream !== null;\n }\n\n async getVideoInputDevices(): Promise<MediaDeviceInfo[]> {\n this.ensureCameraSupport();\n \n try {\n const devices = await navigator.mediaDevices.enumerateDevices();\n return devices.filter(device => device.kind === 'videoinput');\n } catch (error) {\n console.error('[CameraService] Error enumerating video devices:', error);\n throw this.createError('Failed to enumerate video devices', error);\n }\n }\n\n // Direct access to native camera API\n getNativeMediaDevices(): MediaDevices {\n this.ensureCameraSupport();\n return navigator.mediaDevices;\n }\n}\n","import { Injectable } from '@angular/core';\nimport { Observable } from 'rxjs';\nimport { BrowserApiBaseService } from './base/browser-api-base.service';\n\n@Injectable()\nexport class GeolocationService extends BrowserApiBaseService {\n protected override getApiName(): string {\n return 'geolocation';\n }\n\n private ensureGeolocationSupport(): void {\n if (!('geolocation' in navigator)) {\n throw new Error('Geolocation API not supported in this browser');\n }\n }\n\n getCurrentPosition(options?: PositionOptions): Promise<GeolocationPosition> {\n this.ensureGeolocationSupport();\n\n return new Promise((resolve, reject) => {\n navigator.geolocation.getCurrentPosition(\n (position) => resolve(position),\n (error) => {\n console.error('[GeolocationService] Error getting position:', error);\n reject(error);\n },\n options\n );\n });\n }\n\n watchPosition(options?: PositionOptions): Observable<GeolocationPosition> {\n this.ensureGeolocationSupport();\n\n return new Observable<GeolocationPosition>((observer) => {\n const watchId = navigator.geolocation.watchPosition(\n (position) => observer.next(position),\n (error) => {\n console.error('[GeolocationService] Error watching position:', error);\n observer.error(error);\n },\n options\n );\n\n return () => {\n navigator.geolocation.clearWatch(watchId);\n };\n });\n }\n\n clearWatch(watchId: number): void {\n navigator.geolocation.clearWatch(watchId);\n }\n\n // Direct access to native geolocation API\n getNativeGeolocation(): Geolocation {\n this.ensureGeolocationSupport();\n return navigator.geolocation;\n }\n}\n","import { Injectable } from '@angular/core';\nimport { Observable } from 'rxjs';\nimport { BrowserApiBaseService } from './base/browser-api-base.service';\n\ninterface DisplayMediaConstraints {\n video?: boolean | MediaTrackConstraints;\n audio?: boolean | MediaTrackConstraints;\n}\n\n@Injectable()\nexport class MediaDevicesService extends BrowserApiBaseService {\n private createError(message: string, cause: unknown): Error {\n const error = new Error(message) as Error & { cause?: unknown };\n error.cause = cause;\n return error;\n }\n\n protected override getApiName(): string {\n return 'media-devices';\n }\n\n private ensureMediaDevicesSupport(): void {\n if (!('mediaDevices' in navigator)) {\n throw new Error('MediaDevices API not supported in this browser');\n }\n }\n\n async getDevices(): Promise<MediaDeviceInfo[]> {\n this.ensureMediaDevicesSupport();\n\n try {\n const devices = await navigator.mediaDevices.enumerateDevices();\n return devices;\n } catch (error) {\n console.error('[MediaDevicesService] Error enumerating devices:', error);\n throw this.createError('Failed to enumerate media devices', error);\n }\n }\n\n async getUserMedia(constraints?: MediaStreamConstraints): Promise<MediaStream> {\n this.ensureMediaDevicesSupport();\n\n try {\n const defaultConstraints: MediaStreamConstraints = {\n video: true,\n audio: true\n };\n\n const finalConstraints = constraints || defaultConstraints;\n return await navigator.mediaDevices.getUserMedia(finalConstraints);\n } catch (error) {\n console.error('[MediaDevicesService] Error getting user media:', error);\n throw this.handleMediaError(error);\n }\n }\n\n async getDisplayMedia(constraints?: DisplayMediaConstraints): Promise<MediaStream> {\n this.ensureMediaDevicesSupport();\n\n if (!('getDisplayMedia' in navigator.mediaDevices)) {\n throw new Error('Display media API not supported in this browser');\n }\n\n try {\n const defaultConstraints: DisplayMediaConstraints = {\n video: true,\n audio: false\n };\n\n const finalConstraints = constraints || defaultConstraints;\n return await navigator.mediaDevices.getDisplayMedia(finalConstraints);\n } catch (error) {\n console.error('[MediaDevicesService] Error getting display media:', error);\n throw this.createError('Failed to get display media', error);\n }\n }\n\n watchDeviceChanges(): Observable<MediaDeviceInfo[]> {\n this.ensureMediaDevicesSupport();\n\n return new Observable<MediaDeviceInfo[]>((observer) => {\n const handleDeviceChange = async () => {\n try {\n const devices = await navigator.mediaDevices.enumerateDevices();\n observer.next(devices);\n } catch (error) {\n console.error('[MediaDevicesService] Error handling device change:', error);\n }\n };\n\n // Listen for device changes\n navigator.mediaDevices.addEventListener('devicechange', handleDeviceChange);\n\n // Get initial devices\n handleDeviceChange();\n\n return () => {\n navigator.mediaDevices.removeEventListener('devicechange', handleDeviceChange);\n };\n });\n }\n\n getVideoInputDevices(): Promise<MediaDeviceInfo[]> {\n return this.getDevicesByKind('videoinput');\n }\n\n getAudioInputDevices(): Promise<MediaDeviceInfo[]> {\n return this.getDevicesByKind('audioinput');\n }\n\n getAudioOutputDevices(): Promise<MediaDeviceInfo[]> {\n return this.getDevicesByKind('audiooutput');\n }\n\n private async getDevicesByKind(kind: MediaDeviceKind): Promise<MediaDeviceInfo[]> {\n const devices = await this.getDevices();\n return devices.filter(device => device.kind === kind);\n }\n\n private handleMediaError(error: unknown): Error {\n let message: string;\n \n if (error instanceof Error) {\n switch (error.name) {\n case 'NotAllowedError':\n message = 'Permission denied by user';\n break;\n case 'NotFoundError':\n message = 'No media device found';\n break;\n case 'NotReadableError':\n message = 'Media device is already in use';\n break;\n case 'OverconstrainedError':\n message = 'Media constraints cannot be satisfied';\n break;\n case 'TypeError':\n message = 'Invalid media constraints provided';\n break;\n default:\n message = `Media error: ${error.message}`;\n }\n } else {\n message = 'Unknown media error occurred';\n }\n \n return this.createError(message, error);\n }\n\n // Direct access to native media devices API\n getNativeMediaDevices(): MediaDevices {\n this.ensureMediaDevicesSupport();\n return navigator.mediaDevices;\n }\n}\n","import { Injectable } from '@angular/core';\nimport { BrowserApiBaseService } from './base/browser-api-base.service';\n\n\n@Injectable()\nexport class NotificationService extends BrowserApiBaseService {\n protected override getApiName(): string {\n return 'notifications';\n }\n\n async showNotification(title: string, options?: NotificationOptions): Promise<Notification> {\n if (!('Notification' in window)) {\n throw new Error('Notification API not supported in this browser');\n }\n\n const permissionStatus = await this.permissionsService.query({ name: 'notifications' });\n if (permissionStatus.state !== 'granted') {\n throw new Error('Notification permission required. Please grant notification access and try again.');\n }\n\n try {\n return new Notification(title, options);\n } catch (error) {\n console.error('[NotificationService] Error showing notification:', error);\n throw error;\n }\n }\n\n // Direct access to native notification API\n}\n","import { Injectable } from '@angular/core';\nimport { BrowserApiBaseService } from './base/browser-api-base.service';\n\n@Injectable()\nexport class ClipboardService extends BrowserApiBaseService {\n protected override getApiName(): string {\n return 'clipboard';\n }\n\n private async ensureClipboardPermission(action: 'read' | 'write'): Promise<void> {\n if (!('clipboard' in navigator)) {\n throw new Error('Clipboard API not supported in this browser');\n }\n\n const permissionStatus = await this.permissionsService.query({ \n name: `clipboard-${action}` as PermissionName \n });\n if (permissionStatus.state !== 'granted') {\n throw new Error(`Clipboard ${action} permission required. Please grant clipboard access and try again.`);\n }\n }\n\n async writeText(text: string): Promise<void> {\n await this.ensureClipboardPermission('write');\n\n try {\n await navigator.clipboard.writeText(text);\n } catch (error) {\n console.error('[ClipboardService] Error writing to clipboard:', error);\n throw error;\n }\n }\n\n async readText(): Promise<string> {\n await this.ensureClipboardPermission('read');\n\n try {\n return await navigator.clipboard.readText();\n } catch (error) {\n console.error('[ClipboardService] Error reading from clipboard:', error);\n throw error;\n }\n }\n\n async writeTextSecure(text: string): Promise<void> {\n await this.ensureClipboardPermission('write');\n\n try {\n await navigator.clipboard.writeText(text);\n } catch (error) {\n console.error('[ClipboardService] Error writing to clipboard:', error);\n throw error;\n }\n }\n\n // Direct access to native clipboard API\n}\n","import { Injectable } from '@angular/core';\n\nexport type BrowserCapabilityId =\n | 'permissions'\n | 'geolocation'\n | 'clipboard'\n | 'notification'\n | 'mediaDevices'\n | 'camera'\n | 'webWorker'\n | 'regexSecurity'\n | 'webStorage'\n | 'webShare'\n | 'battery'\n | 'webSocket';\n\nconst BROWSER_CAPABILITIES = [\n { id: 'permissions', label: 'Permissions API', requiresSecureContext: false },\n { id: 'geolocation', label: 'Geolocation API', requiresSecureContext: true },\n { id: 'clipboard', label: 'Clipboard API', requiresSecureContext: true },\n { id: 'notification', label: 'Notification API', requiresSecureContext: true },\n { id: 'mediaDevices', label: 'MediaDevices API', requiresSecureContext: true },\n { id: 'camera', label: 'Camera API', requiresSecureContext: true },\n { id: 'webWorker', label: 'Web Worker API', requiresSecureContext: false },\n { id: 'regexSecurity', label: 'Regex Security', requiresSecureContext: false },\n { id: 'webStorage', label: 'Web Storage', requiresSecureContext: false },\n { id: 'webShare', label: 'Web Share', requiresSecureContext: true },\n { id: 'battery', label: 'Battery API', requiresSecureContext: false },\n { id: 'webSocket', label: 'WebSocket API', requiresSecureContext: false }\n] as const satisfies ReadonlyArray<{\n id: BrowserCapabilityId;\n label: string;\n requiresSecureContext: boolean;\n}>;\n\n@Injectable({ providedIn: 'root' })\nexport class BrowserCapabilityService {\n getCapabilities() {\n return BROWSER_CAPABILITIES;\n }\n\n isSecureContext(): boolean {\n return typeof window !== 'undefined' && window.isSecureContext;\n }\n\n isSupported(capability: BrowserCapabilityId): boolean {\n switch (capability) {\n case 'permissions':\n return typeof navigator !== 'undefined' && 'permissions' in navigator;\n case 'geolocation':\n return typeof navigator !== 'undefined' && 'geolocation' in navigator;\n case 'clipboard':\n return typeof navigator !== 'undefined' && 'clipboard' in navigator;\n case 'notification':\n return typeof window !== 'undefined' && 'Notification' in window;\n case 'mediaDevices':\n case 'camera':\n return typeof navigator !== 'undefined' && 'mediaDevices' in navigator;\n case 'webWorker':\n case 'regexSecurity':\n return typeof Worker !== 'undefined';\n case 'webStorage':\n return typeof Storage !== 'undefined';\n case 'webShare':\n return typeof navigator !== 'undefined' && 'share' in navigator;\n case 'battery':\n return typeof navigator !== 'undefined' && 'getBattery' in navigator;\n case 'webSocket':\n return typeof WebSocket !== 'undefined';\n default:\n return false;\n }\n }\n\n getAllStatuses() {\n const secureContext = this.isSecureContext();\n\n return this.getCapabilities().map((capability) => ({\n id: capability.id,\n label: capability.label,\n supported: this.isSupported(capability.id),\n secureContext,\n requiresSecureContext: capability.requiresSecureContext\n }));\n }\n\n async getPermissionState(permission: PermissionName): Promise<PermissionState | 'unknown'> {\n if (typeof navigator === 'undefined' || !('permissions' in navigator)) {\n return 'unknown';\n }\n\n try {\n const status = await navigator.permissions.query({ name: permission as PermissionName });\n return status.state;\n } catch {\n return 'unknown';\n }\n }\n}\n","export class BrowserSupportUtil {\n static isSupported(feature: string): boolean {\n if (typeof window === 'undefined' || typeof navigator === 'undefined') {\n return false;\n }\n\n switch (feature) {\n case 'permissions':\n return 'permissions' in navigator;\n case 'camera':\n return 'mediaDevices' in navigator && 'getUserMedia' in navigator.mediaDevices;\n case 'microphone':\n return 'mediaDevices' in navigator && 'getUserMedia' in navigator.mediaDevices;\n case 'geolocation':\n return 'geolocation' in navigator;\n case 'notifications':\n return 'Notification' in window;\n case 'clipboard':\n return 'clipboard' in navigator;\n case 'clipboard-read':\n return 'clipboard' in navigator && 'readText' in navigator.clipboard;\n case 'clipboard-write':\n return 'clipboard' in navigator && 'writeText' in navigator.clipboard;\n case 'persistent-storage':\n return 'storage' in navigator && 'persist' in navigator.storage;\n default:\n return false;\n }\n }\n\n static getUnsupportedFeatures(): string[] {\n const features = [\n 'permissions',\n 'camera',\n 'microphone',\n 'geolocation',\n 'notifications',\n 'clipboard',\n 'clipboard-read',\n 'clipboard-write',\n 'persistent-storage'\n ];\n \n return features.filter(feature => !this.isSupported(feature));\n }\n\n static isSecureContext(): boolean {\n return typeof window !== 'undefined' ? window.isSecureContext : false;\n }\n\n static getUserAgent(): string {\n return typeof navigator !== 'undefined' ? navigator.userAgent : '';\n }\n\n static isMobile(): boolean {\n const userAgent = this.getUserAgent().toLowerCase();\n return /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(userAgent);\n }\n\n static isDesktop(): boolean {\n return !this.isMobile();\n }\n\n static getBrowserInfo(): {\n name: string;\n version: string;\n isChrome: boolean;\n isFirefox: boolean;\n isSafari: boolean;\n isEdge: boolean;\n } {\n const userAgent = this.getUserAgent();\n \n return {\n name: this.getBrowserName(userAgent),\n version: this.getBrowserVersion(userAgent),\n isChrome: /chrome/.test(userAgent) && !/edge/.test(userAgent),\n isFirefox: /firefox/.test(userAgent),\n isSafari: /safari/.test(userAgent) && !/chrome/.test(userAgent),\n isEdge: /edge/.test(userAgent) || /edg/.test(userAgent)\n };\n }\n\n private static getBrowserName(userAgent: string): string {\n if (/chrome/.test(userAgent) && !/edge/.test(userAgent)) return 'Chrome';\n if (/firefox/.test(userAgent)) return 'Firefox';\n if (/safari/.test(userAgent) && !/chrome/.test(userAgent)) return 'Safari';\n if (/edge/.test(userAgent) || /edg/.test(userAgent)) return 'Edge';\n return 'Unknown';\n }\n\n private static getBrowserVersion(userAgent: string): string {\n const match = userAgent.match(/(chrome|firefox|safari|edge|edg)\\/(\\d+)/i);\n return match ? match[2] : 'Unknown';\n }\n}\n","import { CanActivate, ActivatedRouteSnapshot, Router } from '@angular/router';\nimport { PermissionsService } from '../services/permissions.service';\nimport { PermissionNameExt } from '../interfaces/permissions.interface';\n\nexport class PermissionGuard implements CanActivate {\n constructor(\n private permissionsService: PermissionsService,\n private router: Router\n ) {}\n\n canActivate(route: ActivatedRouteSnapshot): Promise<boolean> {\n const permission = route.data?.['permission'] as PermissionNameExt;\n \n if (!permission) {\n return Promise.resolve(true);\n }\n\n return this.checkPermission(permission);\n }\n\n private async checkPermission(permission: PermissionNameExt): Promise<boolean> {\n try {\n const status = await this.permissionsService.query({ name: permission as PermissionName });\n\n if (status.state !== 'granted') {\n this.router.navigate(['/permission-denied'], {\n queryParams: { permission }\n });\n return false;\n }\n\n return true;\n } catch (error) {\n console.error('Permission guard error:', error);\n this.router.navigate(['/permission-denied'], {\n queryParams: { permission }\n });\n return false;\n }\n }\n}\n\nexport function createPermissionGuard(permission: PermissionNameExt) {\n return {\n canActivate: [PermissionGuard],\n data: { permission }\n };\n}\n","// Browser Web APIs Services\nexport { PermissionsService } from './services/permissions.service';\nexport { CameraService } from './services/camera.service';\nexport { GeolocationService } from './services/geolocation.service';\nexport { MediaDevicesService } from './services/media-devices.service';\nexport { NotificationService } from './services/notification.service';\nexport { ClipboardService } from './services/clipboard.service';\nexport {\n BrowserCapabilityService,\n type BrowserCapabilityId\n} from './services/browser-capability.service';\n\n// Interfaces and Types\nexport * from './interfaces/permissions.interface';\nexport * from './interfaces/media.interface';\nexport * from './interfaces/geolocation.interface';\n\n// Utils and Guards\nexport * from './utils/browser-support.util';\nexport * from './guards/permission.guard';\n\n// Version\nexport const version = '0.1.0';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angular-helpers/browser-web-apis",
|
|
3
|
-
"version": "21.0.
|
|
3
|
+
"version": "21.0.2",
|
|
4
4
|
"description": "Sistema de servicios Angular para acceso formalizado a Browser Web APIs (cámara, permisos, geolocalización, etc.)",
|
|
5
|
-
"main": "dist/browser-web-apis/browser-web-apis.d.ts",
|
|
6
|
-
"types": "dist/browser-web-apis/browser-web-apis.d.ts",
|
|
7
|
-
"files": [
|
|
8
|
-
"dist"
|
|
9
|
-
],
|
|
10
5
|
"keywords": [
|
|
11
6
|
"angular",
|
|
12
7
|
"typescript",
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { DestroyRef } from '@angular/core';
|
|
3
|
+
import { Observable } from 'rxjs';
|
|
4
|
+
import { CanActivate, Router, ActivatedRouteSnapshot } from '@angular/router';
|
|
5
|
+
|
|
6
|
+
type PermissionNameExt = PermissionName | 'clipboard-read' | 'clipboard-write';
|
|
7
|
+
interface PermissionRequest {
|
|
8
|
+
name: PermissionNameExt;
|
|
9
|
+
state: PermissionState;
|
|
10
|
+
}
|
|
11
|
+
interface BrowserPermissions {
|
|
12
|
+
query(descriptor: PermissionDescriptor): Promise<PermissionStatus>;
|
|
13
|
+
isSupported(): boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
declare class PermissionsService implements BrowserPermissions {
|
|
17
|
+
query(descriptor: PermissionDescriptor): Promise<PermissionStatus>;
|
|
18
|
+
isSupported(): boolean;
|
|
19
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<PermissionsService, never>;
|
|
20
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<PermissionsService>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Base class for all Browser Web API services
|
|
25
|
+
* Provides common functionality for:
|
|
26
|
+
* - Support checking
|
|
27
|
+
* - Permission management
|
|
28
|
+
* - Error handling
|
|
29
|
+
* - Lifecycle management with destroyRef
|
|
30
|
+
* - Logging
|
|
31
|
+
*/
|
|
32
|
+
declare abstract class BrowserApiBaseService {
|
|
33
|
+
protected permissionsService: PermissionsService;
|
|
34
|
+
protected destroyRef: DestroyRef;
|
|
35
|
+
protected platformId: Object;
|
|
36
|
+
/**
|
|
37
|
+
* Abstract method that must be implemented by child services
|
|
38
|
+
* Returns the API name for support checking
|
|
39
|
+
*/
|
|
40
|
+
protected abstract getApiName(): string;
|
|
41
|
+
/**
|
|
42
|
+
* Check if running in browser environment using Angular's platform detection
|
|
43
|
+
*/
|
|
44
|
+
protected isBrowserEnvironment(): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Check if running in server environment using Angular's platform detection
|
|
47
|
+
*/
|
|
48
|
+
protected isServerEnvironment(): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Request a permission
|
|
51
|
+
*/
|
|
52
|
+
protected requestPermission(permission: PermissionNameExt): Promise<boolean>;
|
|
53
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BrowserApiBaseService, never>;
|
|
54
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<BrowserApiBaseService>;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
declare class CameraService extends BrowserApiBaseService {
|
|
58
|
+
private currentStream;
|
|
59
|
+
private createError;
|
|
60
|
+
protected getApiName(): string;
|
|
61
|
+
private ensureCameraSupport;
|
|
62
|
+
startCamera(constraints?: MediaStreamConstraints): Promise<MediaStream>;
|
|
63
|
+
stopCamera(): void;
|
|
64
|
+
switchCamera(deviceId: string, constraints?: MediaStreamConstraints): Promise<MediaStream>;
|
|
65
|
+
getCameraCapabilities(deviceId: string): Promise<MediaTrackCapabilities | null>;
|
|
66
|
+
getCurrentStream(): MediaStream | null;
|
|
67
|
+
isStreaming(): boolean;
|
|
68
|
+
getVideoInputDevices(): Promise<MediaDeviceInfo[]>;
|
|
69
|
+
getNativeMediaDevices(): MediaDevices;
|
|
70
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<CameraService, never>;
|
|
71
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<CameraService>;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
declare class GeolocationService extends BrowserApiBaseService {
|
|
75
|
+
protected getApiName(): string;
|
|
76
|
+
private ensureGeolocationSupport;
|
|
77
|
+
getCurrentPosition(options?: PositionOptions): Promise<GeolocationPosition>;
|
|
78
|
+
watchPosition(options?: PositionOptions): Observable<GeolocationPosition>;
|
|
79
|
+
clearWatch(watchId: number): void;
|
|
80
|
+
getNativeGeolocation(): Geolocation;
|
|
81
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<GeolocationService, never>;
|
|
82
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<GeolocationService>;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
interface DisplayMediaConstraints {
|
|
86
|
+
video?: boolean | MediaTrackConstraints;
|
|
87
|
+
audio?: boolean | MediaTrackConstraints;
|
|
88
|
+
}
|
|
89
|
+
declare class MediaDevicesService extends BrowserApiBaseService {
|
|
90
|
+
private createError;
|
|
91
|
+
protected getApiName(): string;
|
|
92
|
+
private ensureMediaDevicesSupport;
|
|
93
|
+
getDevices(): Promise<MediaDeviceInfo[]>;
|
|
94
|
+
getUserMedia(constraints?: MediaStreamConstraints): Promise<MediaStream>;
|
|
95
|
+
getDisplayMedia(constraints?: DisplayMediaConstraints): Promise<MediaStream>;
|
|
96
|
+
watchDeviceChanges(): Observable<MediaDeviceInfo[]>;
|
|
97
|
+
getVideoInputDevices(): Promise<MediaDeviceInfo[]>;
|
|
98
|
+
getAudioInputDevices(): Promise<MediaDeviceInfo[]>;
|
|
99
|
+
getAudioOutputDevices(): Promise<MediaDeviceInfo[]>;
|
|
100
|
+
private getDevicesByKind;
|
|
101
|
+
private handleMediaError;
|
|
102
|
+
getNativeMediaDevices(): MediaDevices;
|
|
103
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<MediaDevicesService, never>;
|
|
104
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<MediaDevicesService>;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
declare class NotificationService extends BrowserApiBaseService {
|
|
108
|
+
protected getApiName(): string;
|
|
109
|
+
showNotification(title: string, options?: NotificationOptions): Promise<Notification>;
|
|
110
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<NotificationService, never>;
|
|
111
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<NotificationService>;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
declare class ClipboardService extends BrowserApiBaseService {
|
|
115
|
+
protected getApiName(): string;
|
|
116
|
+
private ensureClipboardPermission;
|
|
117
|
+
writeText(text: string): Promise<void>;
|
|
118
|
+
readText(): Promise<string>;
|
|
119
|
+
writeTextSecure(text: string): Promise<void>;
|
|
120
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<ClipboardService, never>;
|
|
121
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<ClipboardService>;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
type BrowserCapabilityId = 'permissions' | 'geolocation' | 'clipboard' | 'notification' | 'mediaDevices' | 'camera' | 'webWorker' | 'regexSecurity' | 'webStorage' | 'webShare' | 'battery' | 'webSocket';
|
|
125
|
+
declare class BrowserCapabilityService {
|
|
126
|
+
getCapabilities(): readonly [{
|
|
127
|
+
readonly id: "permissions";
|
|
128
|
+
readonly label: "Permissions API";
|
|
129
|
+
readonly requiresSecureContext: false;
|
|
130
|
+
}, {
|
|
131
|
+
readonly id: "geolocation";
|
|
132
|
+
readonly label: "Geolocation API";
|
|
133
|
+
readonly requiresSecureContext: true;
|
|
134
|
+
}, {
|
|
135
|
+
readonly id: "clipboard";
|
|
136
|
+
readonly label: "Clipboard API";
|
|
137
|
+
readonly requiresSecureContext: true;
|
|
138
|
+
}, {
|
|
139
|
+
readonly id: "notification";
|
|
140
|
+
readonly label: "Notification API";
|
|
141
|
+
readonly requiresSecureContext: true;
|
|
142
|
+
}, {
|
|
143
|
+
readonly id: "mediaDevices";
|
|
144
|
+
readonly label: "MediaDevices API";
|
|
145
|
+
readonly requiresSecureContext: true;
|
|
146
|
+
}, {
|
|
147
|
+
readonly id: "camera";
|
|
148
|
+
readonly label: "Camera API";
|
|
149
|
+
readonly requiresSecureContext: true;
|
|
150
|
+
}, {
|
|
151
|
+
readonly id: "webWorker";
|
|
152
|
+
readonly label: "Web Worker API";
|
|
153
|
+
readonly requiresSecureContext: false;
|
|
154
|
+
}, {
|
|
155
|
+
readonly id: "regexSecurity";
|
|
156
|
+
readonly label: "Regex Security";
|
|
157
|
+
readonly requiresSecureContext: false;
|
|
158
|
+
}, {
|
|
159
|
+
readonly id: "webStorage";
|
|
160
|
+
readonly label: "Web Storage";
|
|
161
|
+
readonly requiresSecureContext: false;
|
|
162
|
+
}, {
|
|
163
|
+
readonly id: "webShare";
|
|
164
|
+
readonly label: "Web Share";
|
|
165
|
+
readonly requiresSecureContext: true;
|
|
166
|
+
}, {
|
|
167
|
+
readonly id: "battery";
|
|
168
|
+
readonly label: "Battery API";
|
|
169
|
+
readonly requiresSecureContext: false;
|
|
170
|
+
}, {
|
|
171
|
+
readonly id: "webSocket";
|
|
172
|
+
readonly label: "WebSocket API";
|
|
173
|
+
readonly requiresSecureContext: false;
|
|
174
|
+
}];
|
|
175
|
+
isSecureContext(): boolean;
|
|
176
|
+
isSupported(capability: BrowserCapabilityId): boolean;
|
|
177
|
+
getAllStatuses(): {
|
|
178
|
+
id: "camera" | "geolocation" | "permissions" | "mediaDevices" | "clipboard" | "notification" | "webWorker" | "regexSecurity" | "webStorage" | "webShare" | "battery" | "webSocket";
|
|
179
|
+
label: "Permissions API" | "Geolocation API" | "Clipboard API" | "Notification API" | "MediaDevices API" | "Camera API" | "Web Worker API" | "Regex Security" | "Web Storage" | "Web Share" | "Battery API" | "WebSocket API";
|
|
180
|
+
supported: boolean;
|
|
181
|
+
secureContext: boolean;
|
|
182
|
+
requiresSecureContext: boolean;
|
|
183
|
+
}[];
|
|
184
|
+
getPermissionState(permission: PermissionName): Promise<PermissionState | 'unknown'>;
|
|
185
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BrowserCapabilityService, never>;
|
|
186
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<BrowserCapabilityService>;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
interface MediaDevice {
|
|
190
|
+
deviceId: string;
|
|
191
|
+
groupId: string;
|
|
192
|
+
kind: MediaDeviceKind;
|
|
193
|
+
label: string;
|
|
194
|
+
}
|
|
195
|
+
type MediaDeviceKind = 'videoinput' | 'audioinput' | 'audiooutput';
|
|
196
|
+
interface MediaStreamConstraints$1 {
|
|
197
|
+
video?: boolean | MediaTrackConstraints$1;
|
|
198
|
+
audio?: boolean | MediaTrackConstraints$1;
|
|
199
|
+
}
|
|
200
|
+
interface MediaTrackConstraints$1 {
|
|
201
|
+
width?: number | ConstrainULong;
|
|
202
|
+
height?: number | ConstrainULong;
|
|
203
|
+
facingMode?: string | ConstrainDOMString;
|
|
204
|
+
deviceId?: string | ConstrainDOMString;
|
|
205
|
+
groupId?: string | ConstrainDOMString;
|
|
206
|
+
frameRate?: number | ConstrainDouble;
|
|
207
|
+
aspectRatio?: number | ConstrainDouble;
|
|
208
|
+
sampleRate?: number | ConstrainULong;
|
|
209
|
+
sampleSize?: number | ConstrainULong;
|
|
210
|
+
echoCancellation?: boolean | ConstrainBoolean;
|
|
211
|
+
noiseSuppression?: boolean | ConstrainBoolean;
|
|
212
|
+
autoGainControl?: boolean | ConstrainBoolean;
|
|
213
|
+
}
|
|
214
|
+
interface CameraCapabilities {
|
|
215
|
+
width: {
|
|
216
|
+
min: number;
|
|
217
|
+
max: number;
|
|
218
|
+
step: number;
|
|
219
|
+
};
|
|
220
|
+
height: {
|
|
221
|
+
min: number;
|
|
222
|
+
max: number;
|
|
223
|
+
step: number;
|
|
224
|
+
};
|
|
225
|
+
aspectRatio: {
|
|
226
|
+
min: number;
|
|
227
|
+
max: number;
|
|
228
|
+
step: number;
|
|
229
|
+
};
|
|
230
|
+
frameRate: {
|
|
231
|
+
min: number;
|
|
232
|
+
max: number;
|
|
233
|
+
step: number;
|
|
234
|
+
};
|
|
235
|
+
facingMode: string[];
|
|
236
|
+
}
|
|
237
|
+
interface CameraInfo {
|
|
238
|
+
deviceId: string;
|
|
239
|
+
label: string;
|
|
240
|
+
capabilities?: CameraCapabilities;
|
|
241
|
+
kind: 'videoinput';
|
|
242
|
+
}
|
|
243
|
+
interface MediaDevicesInfo {
|
|
244
|
+
videoInputs: CameraInfo[];
|
|
245
|
+
audioInputs: MediaDevice[];
|
|
246
|
+
audioOutputs: MediaDevice[];
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
interface GeolocationPosition$1 {
|
|
250
|
+
coords: GeolocationCoordinates;
|
|
251
|
+
timestamp: number;
|
|
252
|
+
}
|
|
253
|
+
interface GeolocationCoordinates {
|
|
254
|
+
latitude: number;
|
|
255
|
+
longitude: number;
|
|
256
|
+
altitude: number | null;
|
|
257
|
+
accuracy: number;
|
|
258
|
+
altitudeAccuracy: number | null;
|
|
259
|
+
heading: number | null;
|
|
260
|
+
speed: number | null;
|
|
261
|
+
}
|
|
262
|
+
interface GeolocationOptions {
|
|
263
|
+
enableHighAccuracy?: boolean;
|
|
264
|
+
timeout?: number;
|
|
265
|
+
maximumAge?: number;
|
|
266
|
+
}
|
|
267
|
+
interface GeolocationError {
|
|
268
|
+
code: number;
|
|
269
|
+
message: string;
|
|
270
|
+
PERMISSION_DENIED: number;
|
|
271
|
+
POSITION_UNAVAILABLE: number;
|
|
272
|
+
TIMEOUT: number;
|
|
273
|
+
}
|
|
274
|
+
interface GeolocationWatchOptions extends GeolocationOptions {
|
|
275
|
+
maximumAge?: number;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
declare class BrowserSupportUtil {
|
|
279
|
+
static isSupported(feature: string): boolean;
|
|
280
|
+
static getUnsupportedFeatures(): string[];
|
|
281
|
+
static isSecureContext(): boolean;
|
|
282
|
+
static getUserAgent(): string;
|
|
283
|
+
static isMobile(): boolean;
|
|
284
|
+
static isDesktop(): boolean;
|
|
285
|
+
static getBrowserInfo(): {
|
|
286
|
+
name: string;
|
|
287
|
+
version: string;
|
|
288
|
+
isChrome: boolean;
|
|
289
|
+
isFirefox: boolean;
|
|
290
|
+
isSafari: boolean;
|
|
291
|
+
isEdge: boolean;
|
|
292
|
+
};
|
|
293
|
+
private static getBrowserName;
|
|
294
|
+
private static getBrowserVersion;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
declare class PermissionGuard implements CanActivate {
|
|
298
|
+
private permissionsService;
|
|
299
|
+
private router;
|
|
300
|
+
constructor(permissionsService: PermissionsService, router: Router);
|
|
301
|
+
canActivate(route: ActivatedRouteSnapshot): Promise<boolean>;
|
|
302
|
+
private checkPermission;
|
|
303
|
+
}
|
|
304
|
+
declare function createPermissionGuard(permission: PermissionNameExt): {
|
|
305
|
+
canActivate: (typeof PermissionGuard)[];
|
|
306
|
+
data: {
|
|
307
|
+
permission: PermissionNameExt;
|
|
308
|
+
};
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
declare const version = "0.1.0";
|
|
312
|
+
|
|
313
|
+
export { BrowserCapabilityService, BrowserSupportUtil, CameraService, ClipboardService, GeolocationService, MediaDevicesService, NotificationService, PermissionGuard, PermissionsService, createPermissionGuard, version };
|
|
314
|
+
export type { BrowserCapabilityId, BrowserPermissions, CameraCapabilities, CameraInfo, GeolocationCoordinates, GeolocationError, GeolocationOptions, GeolocationPosition$1 as GeolocationPosition, GeolocationWatchOptions, MediaDevice, MediaDeviceKind, MediaDevicesInfo, MediaStreamConstraints$1 as MediaStreamConstraints, MediaTrackConstraints$1 as MediaTrackConstraints, PermissionNameExt, PermissionRequest };
|