diff --git a/.gitignore b/.gitignore index 9a0b943e2..161ad2bb3 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ .project .svn/ bin/ +migrate_working_dir/ # IntelliJ related *.iml @@ -38,6 +39,7 @@ android/.settings/ version # Flutter/Dart/Pub related +/pubspec.lock **/doc/api/ .dart_tool/ .flutter-plugins diff --git a/permission_handler_web/.metadata b/permission_handler_web/.metadata new file mode 100644 index 000000000..9596faeed --- /dev/null +++ b/permission_handler_web/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: 796c8ef79279f9c774545b3771238c3098dbefab + channel: stable + +project_type: package diff --git a/permission_handler_web/CHANGELOG.md b/permission_handler_web/CHANGELOG.md new file mode 100644 index 000000000..68199689b --- /dev/null +++ b/permission_handler_web/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.1.0 + +* Adds an initial implementation of Web support for the permission_handler plugin with camera, notifications, and microphone permissions available. diff --git a/permission_handler_web/LICENSE b/permission_handler_web/LICENSE new file mode 100644 index 000000000..f150c8522 --- /dev/null +++ b/permission_handler_web/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Baseflow + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/permission_handler_web/README.md b/permission_handler_web/README.md new file mode 100644 index 000000000..c022fe853 --- /dev/null +++ b/permission_handler_web/README.md @@ -0,0 +1,23 @@ +# permission_handler_web + +[![pub package](https://img.shields.io/pub/v/permission_handler_web.svg)](https://pub.dartlang.org/packages/permission_handler_web) ![Build status](https://github.com/Baseflow/flutter-permission-handler/workflows/permission_handler_web/badge.svg?branch=master) [![style: flutter lints](https://img.shields.io/badge/style-flutter_lints-40c4ff.svg)](https://pub.dev/packages/flutter_lints) + +The official web implementation of the [permission_handler](https://pub.dev/packages/permission_handler) plugin by [Baseflow](https://baseflow.com). + +## Usage + +This is the officially endorsed web implementation of the permission_handler plugin. This means it will automatically be added to your dependencies when you depend on `permission_handler` in your applications pubspec.yaml. + +More detailed instructions on using the API can be found in the [README.md](../permission_handler/README.md) of the [permission_handler](https://pub.dev/packages/permission_handler) package. + +## Issues + +Please file any issues, bugs or feature requests as an issue on our [GitHub](https://github.com/Baseflow/flutter-permission-handler/issues) page. Commercial support is available, you can contact us at . + +## Want to contribute + +If you would like to contribute to the plugin (e.g. by improving the documentation, solving a bug or adding a cool new feature), please carefully review our [contribution guide](../CONTRIBUTING.md) and send us your [pull request](https://github.com/Baseflow/flutter-permission-handler/pulls). + +## Author + +This permission_handler plugin for Flutter is developed by [Baseflow](https://baseflow.com). \ No newline at end of file diff --git a/permission_handler_web/example/.gitignore b/permission_handler_web/example/.gitignore new file mode 100644 index 000000000..24476c5d1 --- /dev/null +++ b/permission_handler_web/example/.gitignore @@ -0,0 +1,44 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/permission_handler_web/example/.metadata b/permission_handler_web/example/.metadata new file mode 100644 index 000000000..30d90a7ef --- /dev/null +++ b/permission_handler_web/example/.metadata @@ -0,0 +1,45 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled. + +version: + revision: 796c8ef79279f9c774545b3771238c3098dbefab + channel: stable + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 796c8ef79279f9c774545b3771238c3098dbefab + base_revision: 796c8ef79279f9c774545b3771238c3098dbefab + - platform: android + create_revision: 796c8ef79279f9c774545b3771238c3098dbefab + base_revision: 796c8ef79279f9c774545b3771238c3098dbefab + - platform: ios + create_revision: 796c8ef79279f9c774545b3771238c3098dbefab + base_revision: 796c8ef79279f9c774545b3771238c3098dbefab + - platform: linux + create_revision: 796c8ef79279f9c774545b3771238c3098dbefab + base_revision: 796c8ef79279f9c774545b3771238c3098dbefab + - platform: macos + create_revision: 796c8ef79279f9c774545b3771238c3098dbefab + base_revision: 796c8ef79279f9c774545b3771238c3098dbefab + - platform: web + create_revision: 796c8ef79279f9c774545b3771238c3098dbefab + base_revision: 796c8ef79279f9c774545b3771238c3098dbefab + - platform: windows + create_revision: 796c8ef79279f9c774545b3771238c3098dbefab + base_revision: 796c8ef79279f9c774545b3771238c3098dbefab + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/permission_handler_web/example/README.md b/permission_handler_web/example/README.md new file mode 100644 index 000000000..2b3fce4c8 --- /dev/null +++ b/permission_handler_web/example/README.md @@ -0,0 +1,16 @@ +# example + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev/), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/permission_handler_web/example/lib/main.dart b/permission_handler_web/example/lib/main.dart new file mode 100644 index 000000000..ea1d95e85 --- /dev/null +++ b/permission_handler_web/example/lib/main.dart @@ -0,0 +1,141 @@ +import 'package:baseflow_plugin_template/baseflow_plugin_template.dart'; +import 'package:flutter/material.dart'; +import 'package:permission_handler_platform_interface/permission_handler_platform_interface.dart'; + +void main() { + runApp(BaseflowPluginExample( + pluginName: 'Permission Handler', + githubURL: 'https://github.com/Baseflow/flutter-permission-handler', + pubDevURL: 'https://pub.dev/packages/permission_handler', + pages: [PermissionHandlerWidget.createPage()])); +} + +///Defines the main theme color +final MaterialColor themeMaterialColor = + BaseflowPluginExample.createMaterialColor( + const Color.fromRGBO(48, 49, 60, 1)); + +/// A Flutter application demonstrating the functionality of this plugin +class PermissionHandlerWidget extends StatefulWidget { + /// Create a page containing the functionality of this plugin + static ExamplePage createPage() { + return ExamplePage( + Icons.location_on, (context) => PermissionHandlerWidget()); + } + + @override + _PermissionHandlerWidgetState createState() => + _PermissionHandlerWidgetState(); +} + +class _PermissionHandlerWidgetState extends State { + @override + Widget build(BuildContext context) { + return Center( + child: ListView( + children: Permission.values + .where((permission) { + return permission != Permission.unknown && + permission != Permission.mediaLibrary && + permission != Permission.photos && + permission != Permission.photosAddOnly && + permission != Permission.reminders && + permission != Permission.appTrackingTransparency && + permission != Permission.criticalAlerts; + }) + .map((permission) => PermissionWidget(permission)) + .toList()), + ); + } +} + +/// Permission widget containing information about the passed [Permission] +class PermissionWidget extends StatefulWidget { + /// Constructs a [PermissionWidget] for the supplied [Permission] + const PermissionWidget(this._permission); + + final Permission _permission; + + @override + _PermissionState createState() => _PermissionState(_permission); +} + +class _PermissionState extends State { + _PermissionState(this._permission); + + final Permission _permission; + final PermissionHandlerPlatform _permissionHandler = + PermissionHandlerPlatform.instance; + PermissionStatus _permissionStatus = PermissionStatus.denied; + + @override + void initState() { + super.initState(); + + _listenForPermissionStatus(); + } + + void _listenForPermissionStatus() async { + final status = await _permissionHandler.checkPermissionStatus(_permission); + setState(() => _permissionStatus = status); + } + + Color getPermissionColor() { + switch (_permissionStatus) { + case PermissionStatus.denied: + return Colors.red; + case PermissionStatus.granted: + return Colors.green; + case PermissionStatus.limited: + return Colors.orange; + default: + return Colors.grey; + } + } + + @override + Widget build(BuildContext context) { + return ListTile( + title: Text( + _permission.toString(), + style: Theme.of(context).textTheme.bodyLarge, + ), + subtitle: Text( + _permissionStatus.toString(), + style: TextStyle(color: getPermissionColor()), + ), + trailing: (_permission is PermissionWithService) + ? IconButton( + icon: const Icon( + Icons.info, + color: Colors.white, + ), + onPressed: () { + checkServiceStatus( + context, _permission as PermissionWithService); + }) + : null, + onTap: () { + requestPermission(_permission); + }, + ); + } + + void checkServiceStatus( + BuildContext context, PermissionWithService permission) async { + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text( + (await _permissionHandler.checkServiceStatus(permission)).toString()), + )); + } + + Future requestPermission(Permission permission) async { + final status = await _permissionHandler.requestPermissions([permission]); + + setState(() { + print(status); + _permissionStatus = status[permission] ?? PermissionStatus.denied; + print(_permissionStatus); + }); + } +} diff --git a/permission_handler_web/example/pubspec.yaml b/permission_handler_web/example/pubspec.yaml new file mode 100644 index 000000000..e63645acf --- /dev/null +++ b/permission_handler_web/example/pubspec.yaml @@ -0,0 +1,81 @@ +name: permission_handler_web_example +description: Demonstrates how to use the permission_handler_web plugin.. + +environment: + sdk: '>=3.0.5 <4.0.0' + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +dependencies: + baseflow_plugin_template: ^2.1.2 + flutter: + sdk: flutter + meta: ^1.3.0 + permission_handler_platform_interface: any + +dev_dependencies: + integration_test: + sdk: flutter + flutter_test: + sdk: flutter + + permission_handler_web: + # When depending on this package from a real application you should use: + # permission_handler_web: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + path: ../ + + url_launcher: ^6.0.12 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages + assets: + - res/images/baseflow_logo_def_light-02.png + - res/images/poweredByBaseflowLogoLight@3x.png + - res/images/logo.png + - res/images/poweredByBaseflow.png diff --git a/permission_handler_web/example/res/images/baseflow_logo_def_light-02.png b/permission_handler_web/example/res/images/baseflow_logo_def_light-02.png new file mode 100644 index 000000000..85f071f27 Binary files /dev/null and b/permission_handler_web/example/res/images/baseflow_logo_def_light-02.png differ diff --git a/permission_handler_web/example/res/images/logo.png b/permission_handler_web/example/res/images/logo.png new file mode 100644 index 000000000..85f071f27 Binary files /dev/null and b/permission_handler_web/example/res/images/logo.png differ diff --git a/permission_handler_web/example/res/images/poweredByBaseflow.png b/permission_handler_web/example/res/images/poweredByBaseflow.png new file mode 100644 index 000000000..36fbdff38 Binary files /dev/null and b/permission_handler_web/example/res/images/poweredByBaseflow.png differ diff --git a/permission_handler_web/example/res/images/poweredByBaseflowLogoLight.png b/permission_handler_web/example/res/images/poweredByBaseflowLogoLight.png new file mode 100644 index 000000000..6b9f1aae1 Binary files /dev/null and b/permission_handler_web/example/res/images/poweredByBaseflowLogoLight.png differ diff --git a/permission_handler_web/example/res/images/poweredByBaseflowLogoLight@2x.png b/permission_handler_web/example/res/images/poweredByBaseflowLogoLight@2x.png new file mode 100644 index 000000000..66901d9ea Binary files /dev/null and b/permission_handler_web/example/res/images/poweredByBaseflowLogoLight@2x.png differ diff --git a/permission_handler_web/example/res/images/poweredByBaseflowLogoLight@3x.png b/permission_handler_web/example/res/images/poweredByBaseflowLogoLight@3x.png new file mode 100644 index 000000000..36fbdff38 Binary files /dev/null and b/permission_handler_web/example/res/images/poweredByBaseflowLogoLight@3x.png differ diff --git a/permission_handler_web/example/web/favicon.png b/permission_handler_web/example/web/favicon.png new file mode 100644 index 000000000..8aaa46ac1 Binary files /dev/null and b/permission_handler_web/example/web/favicon.png differ diff --git a/permission_handler_web/example/web/icons/Icon-192.png b/permission_handler_web/example/web/icons/Icon-192.png new file mode 100644 index 000000000..b749bfef0 Binary files /dev/null and b/permission_handler_web/example/web/icons/Icon-192.png differ diff --git a/permission_handler_web/example/web/icons/Icon-512.png b/permission_handler_web/example/web/icons/Icon-512.png new file mode 100644 index 000000000..88cfd48df Binary files /dev/null and b/permission_handler_web/example/web/icons/Icon-512.png differ diff --git a/permission_handler_web/example/web/icons/Icon-maskable-192.png b/permission_handler_web/example/web/icons/Icon-maskable-192.png new file mode 100644 index 000000000..eb9b4d76e Binary files /dev/null and b/permission_handler_web/example/web/icons/Icon-maskable-192.png differ diff --git a/permission_handler_web/example/web/icons/Icon-maskable-512.png b/permission_handler_web/example/web/icons/Icon-maskable-512.png new file mode 100644 index 000000000..d69c56691 Binary files /dev/null and b/permission_handler_web/example/web/icons/Icon-maskable-512.png differ diff --git a/permission_handler_web/example/web/index.html b/permission_handler_web/example/web/index.html new file mode 100644 index 000000000..be820e83e --- /dev/null +++ b/permission_handler_web/example/web/index.html @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + example + + + + + + + + + + diff --git a/permission_handler_web/example/web/manifest.json b/permission_handler_web/example/web/manifest.json new file mode 100644 index 000000000..096edf8fe --- /dev/null +++ b/permission_handler_web/example/web/manifest.json @@ -0,0 +1,35 @@ +{ + "name": "example", + "short_name": "example", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + }, + { + "src": "icons/Icon-maskable-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "icons/Icon-maskable-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ] +} diff --git a/permission_handler_web/lib/permission_handler_web.dart b/permission_handler_web/lib/permission_handler_web.dart new file mode 100644 index 000000000..49d0a81f2 --- /dev/null +++ b/permission_handler_web/lib/permission_handler_web.dart @@ -0,0 +1,61 @@ +import 'dart:html' as html; +import 'dart:async'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter_web_plugins/flutter_web_plugins.dart'; +import 'package:permission_handler_platform_interface/permission_handler_platform_interface.dart'; +import 'package:permission_handler_web/web_delegate.dart'; + +/// Platform implementation of the permission_handler Flutter plugin. +class WebPermissionHandler extends PermissionHandlerPlatform { + static final html.MediaDevices _devices = html.window.navigator.mediaDevices!; + static final html.Geolocation _geolocation = + html.window.navigator.geolocation; + static final html.Permissions? _htmlPermissions = + html.window.navigator.permissions; + + final WebDelegate _webDelegate; + + /// Registers the web plugin implementation. + static void registerWith(Registrar registrar) { + PermissionHandlerPlatform.instance = WebPermissionHandler( + webDelegate: WebDelegate( + _devices, + _geolocation, + _htmlPermissions, + ), + ); + } + + /// Constructs a WebPermissionHandler. + WebPermissionHandler({ + required WebDelegate webDelegate, + }) : _webDelegate = webDelegate; + + @override + Future> requestPermissions( + List permissions) async { + return _webDelegate.requestPermissions(permissions); + } + + @override + Future checkPermissionStatus(Permission permission) async { + return _webDelegate.checkPermissionStatus(permission); + } + + @override + Future checkServiceStatus(Permission permission) async { + return _webDelegate.checkServiceStatus(permission); + } + + @override + Future shouldShowRequestPermissionRationale( + Permission permission) async { + return SynchronousFuture(false); + } + + @override + Future openAppSettings() { + return SynchronousFuture(false); + } +} diff --git a/permission_handler_web/lib/web_delegate.dart b/permission_handler_web/lib/web_delegate.dart new file mode 100644 index 000000000..63b6eccbd --- /dev/null +++ b/permission_handler_web/lib/web_delegate.dart @@ -0,0 +1,225 @@ +import 'dart:html' as html; +import 'dart:async'; + +import 'package:permission_handler_platform_interface/permission_handler_platform_interface.dart'; + +/// The delegate class for WebPermissionHandler. +/// Used for dependency injection of html.MediaDevices and html.Permissions objects +class WebDelegate { + /// Constructs a WebDelegate. + WebDelegate( + html.MediaDevices? devices, + html.Geolocation? geolocation, + html.Permissions? permissions, + ) : _devices = devices, + _geolocation = geolocation, + _htmlPermissions = permissions; + + /// The html media devices object used to request camera and microphone permissions. + final html.MediaDevices? _devices; + + /// The html geolocation object used to request location permission. + final html.Geolocation? _geolocation; + + /// The html permissions object used to check permission status. + final html.Permissions? _htmlPermissions; + + /// The permission name to request access to the camera. + static const _microphonePermissionName = 'microphone'; + + /// The permission name to request access to the camera. + static const _cameraPermissionName = 'camera'; + + /// The permission name to request notifications from the user. + static const _notificationsPermissionName = 'notifications'; + + /// The permission name to request access to the user's location. + static const _locationPermissionName = 'location'; + + /// The status indicates that permission has been granted by the user. + static const _grantedPermissionStatus = 'granted'; + + /// The status indicates that permission has been denied by the user. + static const _deniedPermissionStatus = 'denied'; + + /// The status indicates that permission can be requested. + static const _promptPermissionStatus = 'prompt'; + + PermissionStatus _toPermissionStatus(String? webPermissionStatus) { + switch (webPermissionStatus) { + case _grantedPermissionStatus: + return PermissionStatus.granted; + case _deniedPermissionStatus: + return PermissionStatus.permanentlyDenied; + case _promptPermissionStatus: + default: + return PermissionStatus.denied; + } + } + + Future _permissionStatusState( + String webPermissionName, html.Permissions? permissions) async { + final webPermissionStatus = + await permissions?.query({'name': webPermissionName}); + return _toPermissionStatus(webPermissionStatus?.state); + } + + Future _requestMicrophonePermission(html.MediaDevices devices) async { + html.MediaStream? mediaStream; + + try { + mediaStream = await devices.getUserMedia({'audio': true}); + + // In browsers, calling [getUserMedia] will start the recording + // automatically right after. This is undesired behavior as + // [requestPermission] is expected to request permission only. + // + // The manual stop action is then needed here for to stop the automatic + // recording. + + if (mediaStream.active!) { + final audioTracks = mediaStream.getAudioTracks(); + if (audioTracks.isNotEmpty) { + audioTracks[0].stop(); + } + } + } on html.DomException { + return false; + } + + return true; + } + + Future _requestCameraPermission(html.MediaDevices devices) async { + html.MediaStream? mediaStream; + + try { + mediaStream = await devices.getUserMedia({'video': true}); + + // In browsers, calling [getUserMedia] will start the recording + // automatically right after. This is undesired behavior as + // [requestPermission] is expected to request permission only. + // + // The manual stop action is then needed here for to stop the automatic + // recording. + + if (mediaStream.active!) { + final videoTracks = mediaStream.getVideoTracks(); + if (videoTracks.isNotEmpty) { + videoTracks[0].stop(); + } + } + } on html.DomException { + return false; + } + + return true; + } + + Future _requestNotificationPermission() async { + bool granted = false; + html.Notification.requestPermission().then((permission) => { + if (permission == "granted") {granted = true} + }); + + return granted; + } + + Future _requestLocationPermission(html.Geolocation geolocation) async { + try { + await geolocation.getCurrentPosition(); + return true; + } on html.PositionError { + return false; + } + } + + Future _requestSingularPermission( + Permission permission) async { + bool permissionGranted = false; + + switch (permission) { + case Permission.microphone: + permissionGranted = await _requestMicrophonePermission(_devices!); + break; + case Permission.camera: + permissionGranted = await _requestCameraPermission(_devices!); + break; + case Permission.notification: + permissionGranted = await _requestNotificationPermission(); + break; + case Permission.location: + permissionGranted = await _requestLocationPermission(_geolocation!); + break; + default: + throw UnsupportedError( + 'The ${permission.toString()} permission is currently not supported on web.', + ); + } + + if (!permissionGranted) { + return PermissionStatus.permanentlyDenied; + } + return PermissionStatus.granted; + } + + /// Requests the user for access to the supplied list of [Permission]s, if + /// they have not already been granted before. + /// + /// Returns a [Map] containing the status per requested [Permission]. + Future> requestPermissions( + List permissions) async { + final Map permissionStatusMap = {}; + + for (final permission in permissions) { + try { + permissionStatusMap[permission] = + await _requestSingularPermission(permission); + } on UnimplementedError { + rethrow; + } + } + return permissionStatusMap; + } + + /// Checks the current status of the given [Permission]. + Future checkPermissionStatus(Permission permission) async { + String webPermissionName; + switch (permission) { + case Permission.microphone: + webPermissionName = _microphonePermissionName; + break; + case Permission.camera: + webPermissionName = _cameraPermissionName; + break; + case Permission.notification: + webPermissionName = _notificationsPermissionName; + break; + case Permission.location: + webPermissionName = _locationPermissionName; + break; + default: + throw UnimplementedError( + 'checkPermissionStatus() has not been implemented for ${permission.toString()} ' + 'on web.', + ); + } + return _permissionStatusState(webPermissionName, _htmlPermissions); + } + + /// Checks the current status of the service associated with the given + /// [Permission]. + Future checkServiceStatus(Permission permission) async { + try { + final permissionStatus = await checkPermissionStatus(permission); + switch (permissionStatus) { + case PermissionStatus.granted: + return ServiceStatus.enabled; + default: + return ServiceStatus.disabled; + } + } on UnimplementedError { + rethrow; + } + } +} diff --git a/permission_handler_web/pubspec.yaml b/permission_handler_web/pubspec.yaml new file mode 100644 index 000000000..40159b01c --- /dev/null +++ b/permission_handler_web/pubspec.yaml @@ -0,0 +1,36 @@ +name: permission_handler_web +description: A new Flutter package project. +version: 0.0.1 +homepage: + +environment: + sdk: '>=3.0.5 <4.0.0' + flutter: ">=3.3.0" + +dependencies: + flutter: + sdk: flutter + flutter_web_plugins: + sdk: flutter + permission_handler_platform_interface: ^3.7.0 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^2.0.0 + mockito: ^5.4.2 + build_runner: ^2.1.2 + test: ^1.24.4 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + + plugin: + implements: permission_handler + platforms: + web: + pluginClass: WebPermissionHandler + fileName: permission_handler_web.dart diff --git a/permission_handler_web/test/permission_handler_web_test.dart b/permission_handler_web/test/permission_handler_web_test.dart new file mode 100644 index 000000000..39674652e --- /dev/null +++ b/permission_handler_web/test/permission_handler_web_test.dart @@ -0,0 +1,259 @@ +import 'dart:html' as html; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/mockito.dart'; +import 'package:mockito/annotations.dart'; +import 'package:permission_handler_platform_interface/permission_handler_platform_interface.dart'; +import 'package:permission_handler_web/web_delegate.dart'; +import 'permission_handler_web_test.mocks.dart'; + +@GenerateMocks([ + html.DomException, + html.Geolocation, + html.Geoposition, + html.MediaDevices, + html.MediaStream, + html.Navigator, + html.Permissions, + html.PermissionStatus, + html.PositionError, + html.Window, +]) +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + final MockDomException domException = MockDomException(); + final MockGeolocation geolocation = MockGeolocation(); + final MockGeoposition geoposition = MockGeoposition(); + final MockMediaDevices mediaDevices = MockMediaDevices(); + final MockMediaStream mediaStream = MockMediaStream(); + final MockNavigator navigator = MockNavigator(); + final MockPermissions permissions = MockPermissions(); + final MockPermissionStatus permissionStatus = MockPermissionStatus(); + final MockPositionError positionError = MockPositionError(); + final MockWindow window = MockWindow(); + + final WebDelegate fakePlugin = + WebDelegate(mediaDevices, geolocation, permissions); + + final List testPermissions = [ + Permission.camera, + Permission.contacts, + Permission.location, + Permission.microphone, + Permission.notification, + ]; + + when(window.navigator).thenReturn(navigator); + when(navigator.mediaDevices).thenReturn(mediaDevices); + when(navigator.geolocation).thenReturn(geolocation); + when(permissions.query(any)).thenAnswer((_) async => permissionStatus); + + // camera stubs + when(mediaStream.active).thenReturn(true); + when(mediaStream.getVideoTracks()).thenReturn(List.empty()); + + // microphone stubs + when(mediaDevices.getUserMedia({'audio': true})) + .thenAnswer((_) async => mediaStream); + when(mediaStream.getAudioTracks()).thenReturn(List.empty()); + + // location stubs + when(geolocation.getCurrentPosition()).thenAnswer((_) async => geoposition); + + test( + 'check permission works for camera before user is prompted for permission', + () async { + when(permissionStatus.state).thenReturn('prompt'); + + // check permissions status before requesting + final preActualStatus = + await fakePlugin.checkPermissionStatus(Permission.camera); + + expect(preActualStatus, PermissionStatus.denied); + }); + test('check permission works for camera after user accepts permission', + () async { + when(permissionStatus.state).thenReturn('granted'); + + // check permissions status after requesting + final postActualStatus = + await fakePlugin.checkPermissionStatus(Permission.camera); + + expect(postActualStatus, PermissionStatus.granted); + }); + test('check permission works for camera after user declines permission', + () async { + when(permissionStatus.state).thenReturn('denied'); + + // check permissions status after requesting + final postActualStatus = + await fakePlugin.checkPermissionStatus(Permission.camera); + + expect(postActualStatus, PermissionStatus.permanentlyDenied); + }); + + test('request permission works for camera if user grants permission', + () async { + when(mediaDevices.getUserMedia({'video': true})) + .thenAnswer((_) async => mediaStream); + + // request permission + final permissionMap = await fakePlugin.requestPermissions(testPermissions); + + expect(permissionMap[Permission.camera], PermissionStatus.granted); + }); + + test('request permission works for camera if user does not grant permission', + () async { + // stubs + when(mediaDevices.getUserMedia({'video': true})).thenThrow(domException); + + // request permission + final permissionMap = await fakePlugin.requestPermissions(testPermissions); + + expect( + permissionMap[Permission.camera], PermissionStatus.permanentlyDenied); + }); + + test( + 'check permission works for microphone before user is prompted for permission', + () async { + when(permissionStatus.state).thenReturn('prompt'); + + // check permissions status before requesting + final preActualStatus = + await fakePlugin.checkPermissionStatus(Permission.microphone); + + expect(preActualStatus, PermissionStatus.denied); + }); + test('check permission works for microphone after user accepts permission', + () async { + when(permissionStatus.state).thenReturn('granted'); + + // check permissions status after requesting + final postActualStatus = + await fakePlugin.checkPermissionStatus(Permission.microphone); + + expect(postActualStatus, PermissionStatus.granted); + }); + test('check permission works for microphone after user declines permission', + () async { + when(permissionStatus.state).thenReturn('denied'); + + // check permissions status after requesting + final postActualStatus = + await fakePlugin.checkPermissionStatus(Permission.microphone); + + expect(postActualStatus, PermissionStatus.permanentlyDenied); + }); + + test('request permission works for microphone if user grants permission', + () async { + when(mediaDevices.getUserMedia({'audio': true})) + .thenAnswer((_) async => mediaStream); + + // request permission + final permissionMap = await fakePlugin.requestPermissions(testPermissions); + + expect(permissionMap[Permission.microphone], PermissionStatus.granted); + }); + test( + 'request permission works for microphone if user does not grant permission', + () async { + // stubs + when(mediaDevices.getUserMedia({'audio': true})).thenThrow(domException); + + // request permission + final permissionMap = await fakePlugin.requestPermissions(testPermissions); + + expect(permissionMap[Permission.microphone], + PermissionStatus.permanentlyDenied); + }); + + test( + 'check permission works for notification before user is prompted for permission', + () async { + when(permissionStatus.state).thenReturn('prompt'); + + // check permissions status before requesting + final preActualStatus = + await fakePlugin.checkPermissionStatus(Permission.notification); + + expect(preActualStatus, PermissionStatus.denied); + }); + test('check permission works for notification after user accepts permission', + () async { + when(permissionStatus.state).thenReturn('granted'); + + // check permissions status after requesting + final postActualStatus = + await fakePlugin.checkPermissionStatus(Permission.notification); + + expect(postActualStatus, PermissionStatus.granted); + }); + test('check permission works for notification after user declines permission', + () async { + when(permissionStatus.state).thenReturn('denied'); + + // check permissions status after requesting + final postActualStatus = + await fakePlugin.checkPermissionStatus(Permission.notification); + + expect(postActualStatus, PermissionStatus.permanentlyDenied); + }); + + test( + 'check permission works for location before user is prompted for permission', + () async { + when(permissionStatus.state).thenReturn('prompt'); + + // check permissions status before requesting + final preActualStatus = + await fakePlugin.checkPermissionStatus(Permission.location); + + expect(preActualStatus, PermissionStatus.denied); + }); + test('check permission works for location after user accepts permission', + () async { + when(permissionStatus.state).thenReturn('granted'); + + // check permissions status after requesting + final postActualStatus = + await fakePlugin.checkPermissionStatus(Permission.location); + + expect(postActualStatus, PermissionStatus.granted); + }); + test('check permission works for location after user declines permission', + () async { + when(permissionStatus.state).thenReturn('denied'); + + // check permissions status after requesting + final postActualStatus = + await fakePlugin.checkPermissionStatus(Permission.location); + + expect(postActualStatus, PermissionStatus.permanentlyDenied); + }); + + test('request permission works for location if user grants permission', + () async { + when(geolocation.getCurrentPosition()).thenAnswer((_) async => geoposition); + + // request permission + final permissionMap = await fakePlugin.requestPermissions(testPermissions); + + expect(permissionMap[Permission.location], PermissionStatus.granted); + }); + test( + 'request permission works for location if user does not grant permission', + () async { + // stubs + when(geolocation.getCurrentPosition()).thenThrow(positionError); + + // request permission + final permissionMap = await fakePlugin.requestPermissions(testPermissions); + + expect( + permissionMap[Permission.location], PermissionStatus.permanentlyDenied); + }); +} diff --git a/permission_handler_web/test/permission_handler_web_test.mocks.dart b/permission_handler_web/test/permission_handler_web_test.mocks.dart new file mode 100644 index 000000000..e6b660e5d --- /dev/null +++ b/permission_handler_web/test/permission_handler_web_test.mocks.dart @@ -0,0 +1,1835 @@ +// Mocks generated by Mockito 5.4.2 from annotations +// in permission_handler_web/test/permission_handler_web_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i3; +import 'dart:html' as _i2; +import 'dart:math' as _i4; + +import 'package:mockito/mockito.dart' as _i1; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class + +class _FakeGeoposition_0 extends _i1.SmartFake implements _i2.Geoposition { + _FakeGeoposition_0( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeEvents_1 extends _i1.SmartFake implements _i2.Events { + _FakeEvents_1( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeMediaStream_2 extends _i1.SmartFake implements _i2.MediaStream { + _FakeMediaStream_2( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeGeolocation_3 extends _i1.SmartFake implements _i2.Geolocation { + _FakeGeolocation_3( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeRelatedApplication_4 extends _i1.SmartFake + implements _i2.RelatedApplication { + _FakeRelatedApplication_4( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakePermissionStatus_5 extends _i1.SmartFake + implements _i2.PermissionStatus { + _FakePermissionStatus_5( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeDocument_6 extends _i1.SmartFake implements _i2.Document { + _FakeDocument_6( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeLocation_7 extends _i1.SmartFake implements _i2.Location { + _FakeLocation_7( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeConsole_8 extends _i1.SmartFake implements _i2.Console { + _FakeConsole_8( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeHistory_9 extends _i1.SmartFake implements _i2.History { + _FakeHistory_9( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeStorage_10 extends _i1.SmartFake implements _i2.Storage { + _FakeStorage_10( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeNavigator_11 extends _i1.SmartFake implements _i2.Navigator { + _FakeNavigator_11( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakePerformance_12 extends _i1.SmartFake implements _i2.Performance { + _FakePerformance_12( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeWindowBase_13 extends _i1.SmartFake implements _i2.WindowBase { + _FakeWindowBase_13( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeFileSystem_14 extends _i1.SmartFake implements _i2.FileSystem { + _FakeFileSystem_14( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeStylePropertyMapReadonly_15 extends _i1.SmartFake + implements _i2.StylePropertyMapReadonly { + _FakeStylePropertyMapReadonly_15( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeMediaQueryList_16 extends _i1.SmartFake + implements _i2.MediaQueryList { + _FakeMediaQueryList_16( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeEntry_17 extends _i1.SmartFake implements _i2.Entry { + _FakeEntry_17( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +/// A class which mocks [DomException]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockDomException extends _i1.Mock implements _i2.DomException { + MockDomException() { + _i1.throwOnMissingStub(this); + } + + @override + String get name => (super.noSuchMethod( + Invocation.getter(#name), + returnValue: '', + ) as String); +} + +/// A class which mocks [Geolocation]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockGeolocation extends _i1.Mock implements _i2.Geolocation { + MockGeolocation() { + _i1.throwOnMissingStub(this); + } + + @override + _i3.Future<_i2.Geoposition> getCurrentPosition({ + bool? enableHighAccuracy, + Duration? timeout, + Duration? maximumAge, + }) => + (super.noSuchMethod( + Invocation.method( + #getCurrentPosition, + [], + { + #enableHighAccuracy: enableHighAccuracy, + #timeout: timeout, + #maximumAge: maximumAge, + }, + ), + returnValue: _i3.Future<_i2.Geoposition>.value(_FakeGeoposition_0( + this, + Invocation.method( + #getCurrentPosition, + [], + { + #enableHighAccuracy: enableHighAccuracy, + #timeout: timeout, + #maximumAge: maximumAge, + }, + ), + )), + ) as _i3.Future<_i2.Geoposition>); + @override + _i3.Stream<_i2.Geoposition> watchPosition({ + bool? enableHighAccuracy, + Duration? timeout, + Duration? maximumAge, + }) => + (super.noSuchMethod( + Invocation.method( + #watchPosition, + [], + { + #enableHighAccuracy: enableHighAccuracy, + #timeout: timeout, + #maximumAge: maximumAge, + }, + ), + returnValue: _i3.Stream<_i2.Geoposition>.empty(), + ) as _i3.Stream<_i2.Geoposition>); +} + +/// A class which mocks [Geoposition]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockGeoposition extends _i1.Mock implements _i2.Geoposition { + MockGeoposition() { + _i1.throwOnMissingStub(this); + } +} + +/// A class which mocks [MediaDevices]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockMediaDevices extends _i1.Mock implements _i2.MediaDevices { + MockMediaDevices() { + _i1.throwOnMissingStub(this); + } + + @override + _i2.Events get on => (super.noSuchMethod( + Invocation.getter(#on), + returnValue: _FakeEvents_1( + this, + Invocation.getter(#on), + ), + ) as _i2.Events); + @override + _i3.Future> enumerateDevices() => (super.noSuchMethod( + Invocation.method( + #enumerateDevices, + [], + ), + returnValue: _i3.Future>.value([]), + ) as _i3.Future>); + @override + Map getSupportedConstraints() => (super.noSuchMethod( + Invocation.method( + #getSupportedConstraints, + [], + ), + returnValue: {}, + ) as Map); + @override + _i3.Future<_i2.MediaStream> getUserMedia( + [Map? constraints]) => + (super.noSuchMethod( + Invocation.method( + #getUserMedia, + [constraints], + ), + returnValue: _i3.Future<_i2.MediaStream>.value(_FakeMediaStream_2( + this, + Invocation.method( + #getUserMedia, + [constraints], + ), + )), + ) as _i3.Future<_i2.MediaStream>); + @override + void addEventListener( + String? type, + _i2.EventListener? listener, [ + bool? useCapture, + ]) => + super.noSuchMethod( + Invocation.method( + #addEventListener, + [ + type, + listener, + useCapture, + ], + ), + returnValueForMissingStub: null, + ); + @override + void removeEventListener( + String? type, + _i2.EventListener? listener, [ + bool? useCapture, + ]) => + super.noSuchMethod( + Invocation.method( + #removeEventListener, + [ + type, + listener, + useCapture, + ], + ), + returnValueForMissingStub: null, + ); + @override + bool dispatchEvent(_i2.Event? event) => (super.noSuchMethod( + Invocation.method( + #dispatchEvent, + [event], + ), + returnValue: false, + ) as bool); +} + +/// A class which mocks [MediaStream]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockMediaStream extends _i1.Mock implements _i2.MediaStream { + MockMediaStream() { + _i1.throwOnMissingStub(this); + } + + @override + _i3.Stream<_i2.Event> get onAddTrack => (super.noSuchMethod( + Invocation.getter(#onAddTrack), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onRemoveTrack => (super.noSuchMethod( + Invocation.getter(#onRemoveTrack), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i2.Events get on => (super.noSuchMethod( + Invocation.getter(#on), + returnValue: _FakeEvents_1( + this, + Invocation.getter(#on), + ), + ) as _i2.Events); + @override + void addTrack(_i2.MediaStreamTrack? track) => super.noSuchMethod( + Invocation.method( + #addTrack, + [track], + ), + returnValueForMissingStub: null, + ); + @override + _i2.MediaStream clone() => (super.noSuchMethod( + Invocation.method( + #clone, + [], + ), + returnValue: _FakeMediaStream_2( + this, + Invocation.method( + #clone, + [], + ), + ), + ) as _i2.MediaStream); + @override + List<_i2.MediaStreamTrack> getAudioTracks() => (super.noSuchMethod( + Invocation.method( + #getAudioTracks, + [], + ), + returnValue: <_i2.MediaStreamTrack>[], + ) as List<_i2.MediaStreamTrack>); + @override + _i2.MediaStreamTrack? getTrackById(String? trackId) => + (super.noSuchMethod(Invocation.method( + #getTrackById, + [trackId], + )) as _i2.MediaStreamTrack?); + @override + List<_i2.MediaStreamTrack> getTracks() => (super.noSuchMethod( + Invocation.method( + #getTracks, + [], + ), + returnValue: <_i2.MediaStreamTrack>[], + ) as List<_i2.MediaStreamTrack>); + @override + List<_i2.MediaStreamTrack> getVideoTracks() => (super.noSuchMethod( + Invocation.method( + #getVideoTracks, + [], + ), + returnValue: <_i2.MediaStreamTrack>[], + ) as List<_i2.MediaStreamTrack>); + @override + void removeTrack(_i2.MediaStreamTrack? track) => super.noSuchMethod( + Invocation.method( + #removeTrack, + [track], + ), + returnValueForMissingStub: null, + ); + @override + void addEventListener( + String? type, + _i2.EventListener? listener, [ + bool? useCapture, + ]) => + super.noSuchMethod( + Invocation.method( + #addEventListener, + [ + type, + listener, + useCapture, + ], + ), + returnValueForMissingStub: null, + ); + @override + void removeEventListener( + String? type, + _i2.EventListener? listener, [ + bool? useCapture, + ]) => + super.noSuchMethod( + Invocation.method( + #removeEventListener, + [ + type, + listener, + useCapture, + ], + ), + returnValueForMissingStub: null, + ); + @override + bool dispatchEvent(_i2.Event? event) => (super.noSuchMethod( + Invocation.method( + #dispatchEvent, + [event], + ), + returnValue: false, + ) as bool); +} + +/// A class which mocks [Navigator]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockNavigator extends _i1.Mock implements _i2.Navigator { + MockNavigator() { + _i1.throwOnMissingStub(this); + } + + @override + String get language => (super.noSuchMethod( + Invocation.getter(#language), + returnValue: '', + ) as String); + @override + _i2.Geolocation get geolocation => (super.noSuchMethod( + Invocation.getter(#geolocation), + returnValue: _FakeGeolocation_3( + this, + Invocation.getter(#geolocation), + ), + ) as _i2.Geolocation); + @override + String get vendor => (super.noSuchMethod( + Invocation.getter(#vendor), + returnValue: '', + ) as String); + @override + String get vendorSub => (super.noSuchMethod( + Invocation.getter(#vendorSub), + returnValue: '', + ) as String); + @override + String get appCodeName => (super.noSuchMethod( + Invocation.getter(#appCodeName), + returnValue: '', + ) as String); + @override + String get appName => (super.noSuchMethod( + Invocation.getter(#appName), + returnValue: '', + ) as String); + @override + String get appVersion => (super.noSuchMethod( + Invocation.getter(#appVersion), + returnValue: '', + ) as String); + @override + String get product => (super.noSuchMethod( + Invocation.getter(#product), + returnValue: '', + ) as String); + @override + String get userAgent => (super.noSuchMethod( + Invocation.getter(#userAgent), + returnValue: '', + ) as String); + @override + List<_i2.Gamepad?> getGamepads() => (super.noSuchMethod( + Invocation.method( + #getGamepads, + [], + ), + returnValue: <_i2.Gamepad?>[], + ) as List<_i2.Gamepad?>); + @override + _i3.Future<_i2.MediaStream> getUserMedia({ + dynamic audio = false, + dynamic video = false, + }) => + (super.noSuchMethod( + Invocation.method( + #getUserMedia, + [], + { + #audio: audio, + #video: video, + }, + ), + returnValue: _i3.Future<_i2.MediaStream>.value(_FakeMediaStream_2( + this, + Invocation.method( + #getUserMedia, + [], + { + #audio: audio, + #video: video, + }, + ), + )), + ) as _i3.Future<_i2.MediaStream>); + @override + void cancelKeyboardLock() => super.noSuchMethod( + Invocation.method( + #cancelKeyboardLock, + [], + ), + returnValueForMissingStub: null, + ); + @override + _i3.Future getBattery() => (super.noSuchMethod( + Invocation.method( + #getBattery, + [], + ), + returnValue: _i3.Future.value(), + ) as _i3.Future); + @override + _i3.Future<_i2.RelatedApplication> getInstalledRelatedApps() => + (super.noSuchMethod( + Invocation.method( + #getInstalledRelatedApps, + [], + ), + returnValue: + _i3.Future<_i2.RelatedApplication>.value(_FakeRelatedApplication_4( + this, + Invocation.method( + #getInstalledRelatedApps, + [], + ), + )), + ) as _i3.Future<_i2.RelatedApplication>); + @override + _i3.Future getVRDisplays() => (super.noSuchMethod( + Invocation.method( + #getVRDisplays, + [], + ), + returnValue: _i3.Future.value(), + ) as _i3.Future); + @override + void registerProtocolHandler( + String? scheme, + String? url, + String? title, + ) => + super.noSuchMethod( + Invocation.method( + #registerProtocolHandler, + [ + scheme, + url, + title, + ], + ), + returnValueForMissingStub: null, + ); + @override + _i3.Future requestKeyboardLock([List? keyCodes]) => + (super.noSuchMethod( + Invocation.method( + #requestKeyboardLock, + [keyCodes], + ), + returnValue: _i3.Future.value(), + ) as _i3.Future); + @override + _i3.Future requestMidiAccess([Map? options]) => + (super.noSuchMethod( + Invocation.method( + #requestMidiAccess, + [options], + ), + returnValue: _i3.Future.value(), + ) as _i3.Future); + @override + _i3.Future requestMediaKeySystemAccess( + String? keySystem, + List>? supportedConfigurations, + ) => + (super.noSuchMethod( + Invocation.method( + #requestMediaKeySystemAccess, + [ + keySystem, + supportedConfigurations, + ], + ), + returnValue: _i3.Future.value(), + ) as _i3.Future); + @override + bool sendBeacon( + String? url, + Object? data, + ) => + (super.noSuchMethod( + Invocation.method( + #sendBeacon, + [ + url, + data, + ], + ), + returnValue: false, + ) as bool); + @override + _i3.Future share([Map? data]) => + (super.noSuchMethod( + Invocation.method( + #share, + [data], + ), + returnValue: _i3.Future.value(), + ) as _i3.Future); +} + +/// A class which mocks [Permissions]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockPermissions extends _i1.Mock implements _i2.Permissions { + MockPermissions() { + _i1.throwOnMissingStub(this); + } + + @override + _i3.Future<_i2.PermissionStatus> query(Map? permission) => + (super.noSuchMethod( + Invocation.method( + #query, + [permission], + ), + returnValue: + _i3.Future<_i2.PermissionStatus>.value(_FakePermissionStatus_5( + this, + Invocation.method( + #query, + [permission], + ), + )), + ) as _i3.Future<_i2.PermissionStatus>); + @override + _i3.Future<_i2.PermissionStatus> request( + Map? permissions) => + (super.noSuchMethod( + Invocation.method( + #request, + [permissions], + ), + returnValue: + _i3.Future<_i2.PermissionStatus>.value(_FakePermissionStatus_5( + this, + Invocation.method( + #request, + [permissions], + ), + )), + ) as _i3.Future<_i2.PermissionStatus>); + @override + _i3.Future<_i2.PermissionStatus> requestAll( + List>? permissions) => + (super.noSuchMethod( + Invocation.method( + #requestAll, + [permissions], + ), + returnValue: + _i3.Future<_i2.PermissionStatus>.value(_FakePermissionStatus_5( + this, + Invocation.method( + #requestAll, + [permissions], + ), + )), + ) as _i3.Future<_i2.PermissionStatus>); + @override + _i3.Future<_i2.PermissionStatus> revoke(Map? permission) => + (super.noSuchMethod( + Invocation.method( + #revoke, + [permission], + ), + returnValue: + _i3.Future<_i2.PermissionStatus>.value(_FakePermissionStatus_5( + this, + Invocation.method( + #revoke, + [permission], + ), + )), + ) as _i3.Future<_i2.PermissionStatus>); +} + +/// A class which mocks [PermissionStatus]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockPermissionStatus extends _i1.Mock implements _i2.PermissionStatus { + MockPermissionStatus() { + _i1.throwOnMissingStub(this); + } + + @override + _i3.Stream<_i2.Event> get onChange => (super.noSuchMethod( + Invocation.getter(#onChange), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i2.Events get on => (super.noSuchMethod( + Invocation.getter(#on), + returnValue: _FakeEvents_1( + this, + Invocation.getter(#on), + ), + ) as _i2.Events); + @override + void addEventListener( + String? type, + _i2.EventListener? listener, [ + bool? useCapture, + ]) => + super.noSuchMethod( + Invocation.method( + #addEventListener, + [ + type, + listener, + useCapture, + ], + ), + returnValueForMissingStub: null, + ); + @override + void removeEventListener( + String? type, + _i2.EventListener? listener, [ + bool? useCapture, + ]) => + super.noSuchMethod( + Invocation.method( + #removeEventListener, + [ + type, + listener, + useCapture, + ], + ), + returnValueForMissingStub: null, + ); + @override + bool dispatchEvent(_i2.Event? event) => (super.noSuchMethod( + Invocation.method( + #dispatchEvent, + [event], + ), + returnValue: false, + ) as bool); +} + +/// A class which mocks [PositionError]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockPositionError extends _i1.Mock implements _i2.PositionError { + MockPositionError() { + _i1.throwOnMissingStub(this); + } +} + +/// A class which mocks [Window]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockWindow extends _i1.Mock implements _i2.Window { + MockWindow() { + _i1.throwOnMissingStub(this); + } + + @override + _i3.Future get animationFrame => (super.noSuchMethod( + Invocation.getter(#animationFrame), + returnValue: _i3.Future.value(0), + ) as _i3.Future); + @override + _i2.Document get document => (super.noSuchMethod( + Invocation.getter(#document), + returnValue: _FakeDocument_6( + this, + Invocation.getter(#document), + ), + ) as _i2.Document); + @override + _i2.Location get location => (super.noSuchMethod( + Invocation.getter(#location), + returnValue: _FakeLocation_7( + this, + Invocation.getter(#location), + ), + ) as _i2.Location); + @override + set location(_i2.LocationBase? value) => super.noSuchMethod( + Invocation.setter( + #location, + value, + ), + returnValueForMissingStub: null, + ); + @override + _i2.Console get console => (super.noSuchMethod( + Invocation.getter(#console), + returnValue: _FakeConsole_8( + this, + Invocation.getter(#console), + ), + ) as _i2.Console); + @override + set defaultStatus(String? value) => super.noSuchMethod( + Invocation.setter( + #defaultStatus, + value, + ), + returnValueForMissingStub: null, + ); + @override + set defaultstatus(String? value) => super.noSuchMethod( + Invocation.setter( + #defaultstatus, + value, + ), + returnValueForMissingStub: null, + ); + @override + num get devicePixelRatio => (super.noSuchMethod( + Invocation.getter(#devicePixelRatio), + returnValue: 0, + ) as num); + @override + _i2.History get history => (super.noSuchMethod( + Invocation.getter(#history), + returnValue: _FakeHistory_9( + this, + Invocation.getter(#history), + ), + ) as _i2.History); + @override + _i2.Storage get localStorage => (super.noSuchMethod( + Invocation.getter(#localStorage), + returnValue: _FakeStorage_10( + this, + Invocation.getter(#localStorage), + ), + ) as _i2.Storage); + @override + set name(String? value) => super.noSuchMethod( + Invocation.setter( + #name, + value, + ), + returnValueForMissingStub: null, + ); + @override + _i2.Navigator get navigator => (super.noSuchMethod( + Invocation.getter(#navigator), + returnValue: _FakeNavigator_11( + this, + Invocation.getter(#navigator), + ), + ) as _i2.Navigator); + @override + set opener(_i2.WindowBase? value) => super.noSuchMethod( + Invocation.setter( + #opener, + value, + ), + returnValueForMissingStub: null, + ); + @override + int get outerHeight => (super.noSuchMethod( + Invocation.getter(#outerHeight), + returnValue: 0, + ) as int); + @override + int get outerWidth => (super.noSuchMethod( + Invocation.getter(#outerWidth), + returnValue: 0, + ) as int); + @override + _i2.Performance get performance => (super.noSuchMethod( + Invocation.getter(#performance), + returnValue: _FakePerformance_12( + this, + Invocation.getter(#performance), + ), + ) as _i2.Performance); + @override + _i2.Storage get sessionStorage => (super.noSuchMethod( + Invocation.getter(#sessionStorage), + returnValue: _FakeStorage_10( + this, + Invocation.getter(#sessionStorage), + ), + ) as _i2.Storage); + @override + set status(String? value) => super.noSuchMethod( + Invocation.setter( + #status, + value, + ), + returnValueForMissingStub: null, + ); + @override + _i3.Stream<_i2.Event> get onContentLoaded => (super.noSuchMethod( + Invocation.getter(#onContentLoaded), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onAbort => (super.noSuchMethod( + Invocation.getter(#onAbort), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onBlur => (super.noSuchMethod( + Invocation.getter(#onBlur), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onCanPlay => (super.noSuchMethod( + Invocation.getter(#onCanPlay), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onCanPlayThrough => (super.noSuchMethod( + Invocation.getter(#onCanPlayThrough), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onChange => (super.noSuchMethod( + Invocation.getter(#onChange), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.MouseEvent> get onClick => (super.noSuchMethod( + Invocation.getter(#onClick), + returnValue: _i3.Stream<_i2.MouseEvent>.empty(), + ) as _i3.Stream<_i2.MouseEvent>); + @override + _i3.Stream<_i2.MouseEvent> get onContextMenu => (super.noSuchMethod( + Invocation.getter(#onContextMenu), + returnValue: _i3.Stream<_i2.MouseEvent>.empty(), + ) as _i3.Stream<_i2.MouseEvent>); + @override + _i3.Stream<_i2.Event> get onDoubleClick => (super.noSuchMethod( + Invocation.getter(#onDoubleClick), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.DeviceMotionEvent> get onDeviceMotion => (super.noSuchMethod( + Invocation.getter(#onDeviceMotion), + returnValue: _i3.Stream<_i2.DeviceMotionEvent>.empty(), + ) as _i3.Stream<_i2.DeviceMotionEvent>); + @override + _i3.Stream<_i2.DeviceOrientationEvent> get onDeviceOrientation => + (super.noSuchMethod( + Invocation.getter(#onDeviceOrientation), + returnValue: _i3.Stream<_i2.DeviceOrientationEvent>.empty(), + ) as _i3.Stream<_i2.DeviceOrientationEvent>); + @override + _i3.Stream<_i2.MouseEvent> get onDrag => (super.noSuchMethod( + Invocation.getter(#onDrag), + returnValue: _i3.Stream<_i2.MouseEvent>.empty(), + ) as _i3.Stream<_i2.MouseEvent>); + @override + _i3.Stream<_i2.MouseEvent> get onDragEnd => (super.noSuchMethod( + Invocation.getter(#onDragEnd), + returnValue: _i3.Stream<_i2.MouseEvent>.empty(), + ) as _i3.Stream<_i2.MouseEvent>); + @override + _i3.Stream<_i2.MouseEvent> get onDragEnter => (super.noSuchMethod( + Invocation.getter(#onDragEnter), + returnValue: _i3.Stream<_i2.MouseEvent>.empty(), + ) as _i3.Stream<_i2.MouseEvent>); + @override + _i3.Stream<_i2.MouseEvent> get onDragLeave => (super.noSuchMethod( + Invocation.getter(#onDragLeave), + returnValue: _i3.Stream<_i2.MouseEvent>.empty(), + ) as _i3.Stream<_i2.MouseEvent>); + @override + _i3.Stream<_i2.MouseEvent> get onDragOver => (super.noSuchMethod( + Invocation.getter(#onDragOver), + returnValue: _i3.Stream<_i2.MouseEvent>.empty(), + ) as _i3.Stream<_i2.MouseEvent>); + @override + _i3.Stream<_i2.MouseEvent> get onDragStart => (super.noSuchMethod( + Invocation.getter(#onDragStart), + returnValue: _i3.Stream<_i2.MouseEvent>.empty(), + ) as _i3.Stream<_i2.MouseEvent>); + @override + _i3.Stream<_i2.MouseEvent> get onDrop => (super.noSuchMethod( + Invocation.getter(#onDrop), + returnValue: _i3.Stream<_i2.MouseEvent>.empty(), + ) as _i3.Stream<_i2.MouseEvent>); + @override + _i3.Stream<_i2.Event> get onDurationChange => (super.noSuchMethod( + Invocation.getter(#onDurationChange), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onEmptied => (super.noSuchMethod( + Invocation.getter(#onEmptied), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onEnded => (super.noSuchMethod( + Invocation.getter(#onEnded), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onError => (super.noSuchMethod( + Invocation.getter(#onError), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onFocus => (super.noSuchMethod( + Invocation.getter(#onFocus), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onHashChange => (super.noSuchMethod( + Invocation.getter(#onHashChange), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onInput => (super.noSuchMethod( + Invocation.getter(#onInput), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onInvalid => (super.noSuchMethod( + Invocation.getter(#onInvalid), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.KeyboardEvent> get onKeyDown => (super.noSuchMethod( + Invocation.getter(#onKeyDown), + returnValue: _i3.Stream<_i2.KeyboardEvent>.empty(), + ) as _i3.Stream<_i2.KeyboardEvent>); + @override + _i3.Stream<_i2.KeyboardEvent> get onKeyPress => (super.noSuchMethod( + Invocation.getter(#onKeyPress), + returnValue: _i3.Stream<_i2.KeyboardEvent>.empty(), + ) as _i3.Stream<_i2.KeyboardEvent>); + @override + _i3.Stream<_i2.KeyboardEvent> get onKeyUp => (super.noSuchMethod( + Invocation.getter(#onKeyUp), + returnValue: _i3.Stream<_i2.KeyboardEvent>.empty(), + ) as _i3.Stream<_i2.KeyboardEvent>); + @override + _i3.Stream<_i2.Event> get onLoad => (super.noSuchMethod( + Invocation.getter(#onLoad), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onLoadedData => (super.noSuchMethod( + Invocation.getter(#onLoadedData), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onLoadedMetadata => (super.noSuchMethod( + Invocation.getter(#onLoadedMetadata), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onLoadStart => (super.noSuchMethod( + Invocation.getter(#onLoadStart), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.MessageEvent> get onMessage => (super.noSuchMethod( + Invocation.getter(#onMessage), + returnValue: _i3.Stream<_i2.MessageEvent>.empty(), + ) as _i3.Stream<_i2.MessageEvent>); + @override + _i3.Stream<_i2.MouseEvent> get onMouseDown => (super.noSuchMethod( + Invocation.getter(#onMouseDown), + returnValue: _i3.Stream<_i2.MouseEvent>.empty(), + ) as _i3.Stream<_i2.MouseEvent>); + @override + _i3.Stream<_i2.MouseEvent> get onMouseEnter => (super.noSuchMethod( + Invocation.getter(#onMouseEnter), + returnValue: _i3.Stream<_i2.MouseEvent>.empty(), + ) as _i3.Stream<_i2.MouseEvent>); + @override + _i3.Stream<_i2.MouseEvent> get onMouseLeave => (super.noSuchMethod( + Invocation.getter(#onMouseLeave), + returnValue: _i3.Stream<_i2.MouseEvent>.empty(), + ) as _i3.Stream<_i2.MouseEvent>); + @override + _i3.Stream<_i2.MouseEvent> get onMouseMove => (super.noSuchMethod( + Invocation.getter(#onMouseMove), + returnValue: _i3.Stream<_i2.MouseEvent>.empty(), + ) as _i3.Stream<_i2.MouseEvent>); + @override + _i3.Stream<_i2.MouseEvent> get onMouseOut => (super.noSuchMethod( + Invocation.getter(#onMouseOut), + returnValue: _i3.Stream<_i2.MouseEvent>.empty(), + ) as _i3.Stream<_i2.MouseEvent>); + @override + _i3.Stream<_i2.MouseEvent> get onMouseOver => (super.noSuchMethod( + Invocation.getter(#onMouseOver), + returnValue: _i3.Stream<_i2.MouseEvent>.empty(), + ) as _i3.Stream<_i2.MouseEvent>); + @override + _i3.Stream<_i2.MouseEvent> get onMouseUp => (super.noSuchMethod( + Invocation.getter(#onMouseUp), + returnValue: _i3.Stream<_i2.MouseEvent>.empty(), + ) as _i3.Stream<_i2.MouseEvent>); + @override + _i3.Stream<_i2.WheelEvent> get onMouseWheel => (super.noSuchMethod( + Invocation.getter(#onMouseWheel), + returnValue: _i3.Stream<_i2.WheelEvent>.empty(), + ) as _i3.Stream<_i2.WheelEvent>); + @override + _i3.Stream<_i2.Event> get onOffline => (super.noSuchMethod( + Invocation.getter(#onOffline), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onOnline => (super.noSuchMethod( + Invocation.getter(#onOnline), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onPageHide => (super.noSuchMethod( + Invocation.getter(#onPageHide), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onPageShow => (super.noSuchMethod( + Invocation.getter(#onPageShow), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onPause => (super.noSuchMethod( + Invocation.getter(#onPause), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onPlay => (super.noSuchMethod( + Invocation.getter(#onPlay), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onPlaying => (super.noSuchMethod( + Invocation.getter(#onPlaying), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.PopStateEvent> get onPopState => (super.noSuchMethod( + Invocation.getter(#onPopState), + returnValue: _i3.Stream<_i2.PopStateEvent>.empty(), + ) as _i3.Stream<_i2.PopStateEvent>); + @override + _i3.Stream<_i2.Event> get onProgress => (super.noSuchMethod( + Invocation.getter(#onProgress), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onRateChange => (super.noSuchMethod( + Invocation.getter(#onRateChange), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onReset => (super.noSuchMethod( + Invocation.getter(#onReset), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onResize => (super.noSuchMethod( + Invocation.getter(#onResize), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onScroll => (super.noSuchMethod( + Invocation.getter(#onScroll), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onSearch => (super.noSuchMethod( + Invocation.getter(#onSearch), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onSeeked => (super.noSuchMethod( + Invocation.getter(#onSeeked), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onSeeking => (super.noSuchMethod( + Invocation.getter(#onSeeking), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onSelect => (super.noSuchMethod( + Invocation.getter(#onSelect), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onStalled => (super.noSuchMethod( + Invocation.getter(#onStalled), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.StorageEvent> get onStorage => (super.noSuchMethod( + Invocation.getter(#onStorage), + returnValue: _i3.Stream<_i2.StorageEvent>.empty(), + ) as _i3.Stream<_i2.StorageEvent>); + @override + _i3.Stream<_i2.Event> get onSubmit => (super.noSuchMethod( + Invocation.getter(#onSubmit), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onSuspend => (super.noSuchMethod( + Invocation.getter(#onSuspend), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onTimeUpdate => (super.noSuchMethod( + Invocation.getter(#onTimeUpdate), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.TouchEvent> get onTouchCancel => (super.noSuchMethod( + Invocation.getter(#onTouchCancel), + returnValue: _i3.Stream<_i2.TouchEvent>.empty(), + ) as _i3.Stream<_i2.TouchEvent>); + @override + _i3.Stream<_i2.TouchEvent> get onTouchEnd => (super.noSuchMethod( + Invocation.getter(#onTouchEnd), + returnValue: _i3.Stream<_i2.TouchEvent>.empty(), + ) as _i3.Stream<_i2.TouchEvent>); + @override + _i3.Stream<_i2.TouchEvent> get onTouchMove => (super.noSuchMethod( + Invocation.getter(#onTouchMove), + returnValue: _i3.Stream<_i2.TouchEvent>.empty(), + ) as _i3.Stream<_i2.TouchEvent>); + @override + _i3.Stream<_i2.TouchEvent> get onTouchStart => (super.noSuchMethod( + Invocation.getter(#onTouchStart), + returnValue: _i3.Stream<_i2.TouchEvent>.empty(), + ) as _i3.Stream<_i2.TouchEvent>); + @override + _i3.Stream<_i2.TransitionEvent> get onTransitionEnd => (super.noSuchMethod( + Invocation.getter(#onTransitionEnd), + returnValue: _i3.Stream<_i2.TransitionEvent>.empty(), + ) as _i3.Stream<_i2.TransitionEvent>); + @override + _i3.Stream<_i2.Event> get onUnload => (super.noSuchMethod( + Invocation.getter(#onUnload), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onVolumeChange => (super.noSuchMethod( + Invocation.getter(#onVolumeChange), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.Event> get onWaiting => (super.noSuchMethod( + Invocation.getter(#onWaiting), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.AnimationEvent> get onAnimationEnd => (super.noSuchMethod( + Invocation.getter(#onAnimationEnd), + returnValue: _i3.Stream<_i2.AnimationEvent>.empty(), + ) as _i3.Stream<_i2.AnimationEvent>); + @override + _i3.Stream<_i2.AnimationEvent> get onAnimationIteration => + (super.noSuchMethod( + Invocation.getter(#onAnimationIteration), + returnValue: _i3.Stream<_i2.AnimationEvent>.empty(), + ) as _i3.Stream<_i2.AnimationEvent>); + @override + _i3.Stream<_i2.AnimationEvent> get onAnimationStart => (super.noSuchMethod( + Invocation.getter(#onAnimationStart), + returnValue: _i3.Stream<_i2.AnimationEvent>.empty(), + ) as _i3.Stream<_i2.AnimationEvent>); + @override + _i3.Stream<_i2.Event> get onBeforeUnload => (super.noSuchMethod( + Invocation.getter(#onBeforeUnload), + returnValue: _i3.Stream<_i2.Event>.empty(), + ) as _i3.Stream<_i2.Event>); + @override + _i3.Stream<_i2.WheelEvent> get onWheel => (super.noSuchMethod( + Invocation.getter(#onWheel), + returnValue: _i3.Stream<_i2.WheelEvent>.empty(), + ) as _i3.Stream<_i2.WheelEvent>); + @override + int get pageXOffset => (super.noSuchMethod( + Invocation.getter(#pageXOffset), + returnValue: 0, + ) as int); + @override + int get pageYOffset => (super.noSuchMethod( + Invocation.getter(#pageYOffset), + returnValue: 0, + ) as int); + @override + int get scrollX => (super.noSuchMethod( + Invocation.getter(#scrollX), + returnValue: 0, + ) as int); + @override + int get scrollY => (super.noSuchMethod( + Invocation.getter(#scrollY), + returnValue: 0, + ) as int); + @override + _i2.Events get on => (super.noSuchMethod( + Invocation.getter(#on), + returnValue: _FakeEvents_1( + this, + Invocation.getter(#on), + ), + ) as _i2.Events); + @override + _i2.WindowBase open( + String? url, + String? name, [ + String? options, + ]) => + (super.noSuchMethod( + Invocation.method( + #open, + [ + url, + name, + options, + ], + ), + returnValue: _FakeWindowBase_13( + this, + Invocation.method( + #open, + [ + url, + name, + options, + ], + ), + ), + ) as _i2.WindowBase); + @override + int requestAnimationFrame(_i2.FrameRequestCallback? callback) => + (super.noSuchMethod( + Invocation.method( + #requestAnimationFrame, + [callback], + ), + returnValue: 0, + ) as int); + @override + void cancelAnimationFrame(int? id) => super.noSuchMethod( + Invocation.method( + #cancelAnimationFrame, + [id], + ), + returnValueForMissingStub: null, + ); + @override + _i3.Future<_i2.FileSystem> requestFileSystem( + int? size, { + bool? persistent = false, + }) => + (super.noSuchMethod( + Invocation.method( + #requestFileSystem, + [size], + {#persistent: persistent}, + ), + returnValue: _i3.Future<_i2.FileSystem>.value(_FakeFileSystem_14( + this, + Invocation.method( + #requestFileSystem, + [size], + {#persistent: persistent}, + ), + )), + ) as _i3.Future<_i2.FileSystem>); + @override + void alert([String? message]) => super.noSuchMethod( + Invocation.method( + #alert, + [message], + ), + returnValueForMissingStub: null, + ); + @override + void cancelIdleCallback(int? handle) => super.noSuchMethod( + Invocation.method( + #cancelIdleCallback, + [handle], + ), + returnValueForMissingStub: null, + ); + @override + void close() => super.noSuchMethod( + Invocation.method( + #close, + [], + ), + returnValueForMissingStub: null, + ); + @override + bool confirm([String? message]) => (super.noSuchMethod( + Invocation.method( + #confirm, + [message], + ), + returnValue: false, + ) as bool); + @override + _i3.Future fetch( + dynamic input, [ + Map? init, + ]) => + (super.noSuchMethod( + Invocation.method( + #fetch, + [ + input, + init, + ], + ), + returnValue: _i3.Future.value(), + ) as _i3.Future); + @override + bool find( + String? string, + bool? caseSensitive, + bool? backwards, + bool? wrap, + bool? wholeWord, + bool? searchInFrames, + bool? showDialog, + ) => + (super.noSuchMethod( + Invocation.method( + #find, + [ + string, + caseSensitive, + backwards, + wrap, + wholeWord, + searchInFrames, + showDialog, + ], + ), + returnValue: false, + ) as bool); + @override + _i2.StylePropertyMapReadonly getComputedStyleMap( + _i2.Element? element, + String? pseudoElement, + ) => + (super.noSuchMethod( + Invocation.method( + #getComputedStyleMap, + [ + element, + pseudoElement, + ], + ), + returnValue: _FakeStylePropertyMapReadonly_15( + this, + Invocation.method( + #getComputedStyleMap, + [ + element, + pseudoElement, + ], + ), + ), + ) as _i2.StylePropertyMapReadonly); + @override + List<_i2.CssRule> getMatchedCssRules( + _i2.Element? element, + String? pseudoElement, + ) => + (super.noSuchMethod( + Invocation.method( + #getMatchedCssRules, + [ + element, + pseudoElement, + ], + ), + returnValue: <_i2.CssRule>[], + ) as List<_i2.CssRule>); + @override + _i2.MediaQueryList matchMedia(String? query) => (super.noSuchMethod( + Invocation.method( + #matchMedia, + [query], + ), + returnValue: _FakeMediaQueryList_16( + this, + Invocation.method( + #matchMedia, + [query], + ), + ), + ) as _i2.MediaQueryList); + @override + void moveBy( + int? x, + int? y, + ) => + super.noSuchMethod( + Invocation.method( + #moveBy, + [ + x, + y, + ], + ), + returnValueForMissingStub: null, + ); + @override + void postMessage( + dynamic message, + String? targetOrigin, [ + List? transfer, + ]) => + super.noSuchMethod( + Invocation.method( + #postMessage, + [ + message, + targetOrigin, + transfer, + ], + ), + returnValueForMissingStub: null, + ); + @override + void print() => super.noSuchMethod( + Invocation.method( + #print, + [], + ), + returnValueForMissingStub: null, + ); + @override + int requestIdleCallback( + _i2.IdleRequestCallback? callback, [ + Map? options, + ]) => + (super.noSuchMethod( + Invocation.method( + #requestIdleCallback, + [ + callback, + options, + ], + ), + returnValue: 0, + ) as int); + @override + void resizeBy( + int? x, + int? y, + ) => + super.noSuchMethod( + Invocation.method( + #resizeBy, + [ + x, + y, + ], + ), + returnValueForMissingStub: null, + ); + @override + void resizeTo( + int? x, + int? y, + ) => + super.noSuchMethod( + Invocation.method( + #resizeTo, + [ + x, + y, + ], + ), + returnValueForMissingStub: null, + ); + @override + void scroll([ + dynamic options_OR_x, + dynamic y, + Map? scrollOptions, + ]) => + super.noSuchMethod( + Invocation.method( + #scroll, + [ + options_OR_x, + y, + scrollOptions, + ], + ), + returnValueForMissingStub: null, + ); + @override + void scrollBy([ + dynamic options_OR_x, + dynamic y, + Map? scrollOptions, + ]) => + super.noSuchMethod( + Invocation.method( + #scrollBy, + [ + options_OR_x, + y, + scrollOptions, + ], + ), + returnValueForMissingStub: null, + ); + @override + void scrollTo([ + dynamic options_OR_x, + dynamic y, + Map? scrollOptions, + ]) => + super.noSuchMethod( + Invocation.method( + #scrollTo, + [ + options_OR_x, + y, + scrollOptions, + ], + ), + returnValueForMissingStub: null, + ); + @override + void stop() => super.noSuchMethod( + Invocation.method( + #stop, + [], + ), + returnValueForMissingStub: null, + ); + @override + _i3.Future<_i2.Entry> resolveLocalFileSystemUrl(String? url) => + (super.noSuchMethod( + Invocation.method( + #resolveLocalFileSystemUrl, + [url], + ), + returnValue: _i3.Future<_i2.Entry>.value(_FakeEntry_17( + this, + Invocation.method( + #resolveLocalFileSystemUrl, + [url], + ), + )), + ) as _i3.Future<_i2.Entry>); + @override + String atob(String? atob) => (super.noSuchMethod( + Invocation.method( + #atob, + [atob], + ), + returnValue: '', + ) as String); + @override + String btoa(String? btoa) => (super.noSuchMethod( + Invocation.method( + #btoa, + [btoa], + ), + returnValue: '', + ) as String); + @override + void moveTo(_i4.Point? p) => super.noSuchMethod( + Invocation.method( + #moveTo, + [p], + ), + returnValueForMissingStub: null, + ); + @override + void addEventListener( + String? type, + _i2.EventListener? listener, [ + bool? useCapture, + ]) => + super.noSuchMethod( + Invocation.method( + #addEventListener, + [ + type, + listener, + useCapture, + ], + ), + returnValueForMissingStub: null, + ); + @override + void removeEventListener( + String? type, + _i2.EventListener? listener, [ + bool? useCapture, + ]) => + super.noSuchMethod( + Invocation.method( + #removeEventListener, + [ + type, + listener, + useCapture, + ], + ), + returnValueForMissingStub: null, + ); + @override + bool dispatchEvent(_i2.Event? event) => (super.noSuchMethod( + Invocation.method( + #dispatchEvent, + [event], + ), + returnValue: false, + ) as bool); +}