reimplement flashlight delegate & use media capabilities which is more supported
Showing
1 changed file
with
78 additions
and
0 deletions
lib/src/web/flashlight_delegate.dart
0 → 100644
| 1 | +import 'dart:js_interop'; | ||
| 2 | + | ||
| 3 | +import 'package:mobile_scanner/src/enums/torch_state.dart'; | ||
| 4 | +import 'package:web/web.dart'; | ||
| 5 | + | ||
| 6 | +/// This class represents a flashlight delegate for the web platform. | ||
| 7 | +/// | ||
| 8 | +/// It provides an interface to query and update the flashlight state of a [MediaStream]. | ||
| 9 | +final class FlashlightDelegate { | ||
| 10 | + /// Returns a list of supported flashlight modes for the given [mediaStream]. | ||
| 11 | + /// | ||
| 12 | + /// The [TorchState.off] mode is always supported, regardless of the return value. | ||
| 13 | + Future<List<TorchState>> getSupportedFlashlightModes(MediaStream? mediaStream) async { | ||
| 14 | + if (mediaStream == null) { | ||
| 15 | + return []; | ||
| 16 | + } | ||
| 17 | + | ||
| 18 | + final List<JSAny?> tracks = mediaStream.getVideoTracks().toDart; | ||
| 19 | + | ||
| 20 | + if (tracks.isEmpty) { | ||
| 21 | + return []; | ||
| 22 | + } | ||
| 23 | + | ||
| 24 | + final MediaStreamTrack? track = tracks.first as MediaStreamTrack?; | ||
| 25 | + | ||
| 26 | + if (track == null) { | ||
| 27 | + return []; | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + try { | ||
| 31 | + final MediaTrackCapabilities capabilities = track.getCapabilities(); | ||
| 32 | + | ||
| 33 | + return [ | ||
| 34 | + if (capabilities.torch) TorchState.on, | ||
| 35 | + ]; | ||
| 36 | + } catch (_) { | ||
| 37 | + // Firefox does not support getCapabilities() yet. | ||
| 38 | + // https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack/getCapabilities#browser_compatibility | ||
| 39 | + | ||
| 40 | + return []; | ||
| 41 | + } | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + /// Returns whether the given [mediaStream] has a flashlight. | ||
| 45 | + Future<bool> hasFlashlight(MediaStream? mediaStream) async { | ||
| 46 | + return (await getSupportedFlashlightModes(mediaStream)).isNotEmpty; | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + /// Set the flashlight state of the given [mediaStream] to the given [value]. | ||
| 50 | + Future<void> setFlashlightState(MediaStream? mediaStream, TorchState value) async { | ||
| 51 | + if (mediaStream == null) { | ||
| 52 | + return; | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + if (await hasFlashlight(mediaStream)) { | ||
| 56 | + final List<JSAny?> tracks = mediaStream.getVideoTracks().toDart; | ||
| 57 | + | ||
| 58 | + if (tracks.isEmpty) { | ||
| 59 | + return; | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + final bool flashlightEnabled = switch (value) { | ||
| 63 | + TorchState.on => true, | ||
| 64 | + TorchState.off || TorchState.unavailable => false, | ||
| 65 | + }; | ||
| 66 | + | ||
| 67 | + final MediaStreamTrack? track = tracks.first as MediaStreamTrack?; | ||
| 68 | + | ||
| 69 | + final MediaTrackConstraints constraints = MediaTrackConstraints( | ||
| 70 | + advanced: [ | ||
| 71 | + {'torch': flashlightEnabled}.jsify(), | ||
| 72 | + ].toJS, | ||
| 73 | + ); | ||
| 74 | + | ||
| 75 | + await track?.applyConstraints(constraints).toDart; | ||
| 76 | + } | ||
| 77 | + } | ||
| 78 | +} |
-
Please register or login to post a comment