diff --git a/packages/connectivity/connectivity_for_web/CHANGELOG.md b/packages/connectivity/connectivity_for_web/CHANGELOG.md index 89e186abe1cb..83dc386a0314 100644 --- a/packages/connectivity/connectivity_for_web/CHANGELOG.md +++ b/packages/connectivity/connectivity_for_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.3.1 + +* Use NetworkInformation API from dart:html, instead of the JS-interop version. + ## 0.3.0 * Rename from "experimental_connectivity_web" to "connectivity_for_web", and move to flutter/plugins master. diff --git a/packages/connectivity/connectivity_for_web/lib/src/generated/network_information_types.dart b/packages/connectivity/connectivity_for_web/lib/src/generated/network_information_types.dart deleted file mode 100644 index c4045b3ec1fc..000000000000 --- a/packages/connectivity/connectivity_for_web/lib/src/generated/network_information_types.dart +++ /dev/null @@ -1,78 +0,0 @@ -@JS() -library network_information_types; - -import "package:js/js.dart"; -import "dart:html" show EventListener, EventTarget; - -/// W3C Spec Draft http://wicg.github.io/netinfo/ -/// Edition: Draft Community Group Report 20 February 2019 - -/// http://wicg.github.io/netinfo/#navigatornetworkinformation-interface -@anonymous -@JS() -abstract class Navigator implements NavigatorNetworkInformation {} - -@anonymous -@JS() -abstract class WorkerNavigator implements NavigatorNetworkInformation { - external factory WorkerNavigator({NetworkInformation connection}); -} - -/// http://wicg.github.io/netinfo/#navigatornetworkinformation-interface -@anonymous -@JS() -abstract class NavigatorNetworkInformation { - external NetworkInformation get connection; - external factory NavigatorNetworkInformation({NetworkInformation connection}); -} - -/// http://wicg.github.io/netinfo/#connection-types -/*type ConnectionType = - | 'bluetooth' - | 'cellular' - | 'ethernet' - | 'mixed' - | 'none' - | 'other' - | 'unknown' - | 'wifi' - | 'wimax'; -*/ - -/// http://wicg.github.io/netinfo/#effectiveconnectiontype-enum -/*type EffectiveConnectionType = '2g' | '3g' | '4g' | 'slow-2g';*/ - -/// http://wicg.github.io/netinfo/#dom-megabit -/*type Megabit = number;*/ -/// http://wicg.github.io/netinfo/#dom-millisecond -/*type Millisecond = number;*/ - -/// http://wicg.github.io/netinfo/#networkinformation-interface -@anonymous -@JS() -abstract class NetworkInformation implements EventTarget { - /// http://wicg.github.io/netinfo/#type-attribute - external String /*'bluetooth'|'cellular'|'ethernet'|'mixed'|'none'|'other'|'unknown'|'wifi'|'wimax'*/ get type; - - /// http://wicg.github.io/netinfo/#effectivetype-attribute - external String /*'2g'|'3g'|'4g'|'slow-2g'*/ get effectiveType; - - /// http://wicg.github.io/netinfo/#downlinkmax-attribute - external num get downlinkMax; - - /// http://wicg.github.io/netinfo/#downlink-attribute - external num get downlink; - - /// http://wicg.github.io/netinfo/#rtt-attribute - external num get rtt; - - /// http://wicg.github.io/netinfo/#savedata-attribute - external bool get saveData; - - /// http://wicg.github.io/netinfo/#handling-changes-to-the-underlying-connection - external EventListener get onchange; - external set onchange(EventListener v); -} - -@JS() -external Navigator get navigator; diff --git a/packages/connectivity/connectivity_for_web/lib/src/network_information_api_connectivity_plugin.dart b/packages/connectivity/connectivity_for_web/lib/src/network_information_api_connectivity_plugin.dart index d88487b9c406..99bac2ab8d30 100644 --- a/packages/connectivity/connectivity_for_web/lib/src/network_information_api_connectivity_plugin.dart +++ b/packages/connectivity/connectivity_for_web/lib/src/network_information_api_connectivity_plugin.dart @@ -1,28 +1,29 @@ import 'dart:async'; +import 'dart:html' as html show window, NetworkInformation; +import 'dart:js'; +import 'dart:js_util'; import 'package:connectivity_platform_interface/connectivity_platform_interface.dart'; import 'package:connectivity_for_web/connectivity_for_web.dart'; import 'package:flutter/foundation.dart'; -import 'package:js/js.dart'; -import 'generated/network_information_types.dart' as dom; import 'utils/connectivity_result.dart'; /// The web implementation of the ConnectivityPlatform of the Connectivity plugin. class NetworkInformationApiConnectivityPlugin extends ConnectivityPlugin { - final dom.NetworkInformation _networkInformation; + final html.NetworkInformation _networkInformation; /// A check to determine if this version of the plugin can be used. - static bool isSupported() => dom.navigator?.connection != null; + static bool isSupported() => html.window.navigator.connection != null; /// The constructor of the plugin. NetworkInformationApiConnectivityPlugin() - : this.withConnection(dom.navigator?.connection); + : this.withConnection(html.window.navigator.connection); /// Creates the plugin, with an override of the NetworkInformation object. @visibleForTesting NetworkInformationApiConnectivityPlugin.withConnection( - dom.NetworkInformation connection) + html.NetworkInformation connection) : _networkInformation = connection; /// Checks the connection status of the device. @@ -31,18 +32,30 @@ class NetworkInformationApiConnectivityPlugin extends ConnectivityPlugin { return networkInformationToConnectivityResult(_networkInformation); } - StreamController _connectivityResult; + StreamController _connectivityResultStreamController; + Stream _connectivityResultStream; /// Returns a Stream of ConnectivityResults changes. @override Stream get onConnectivityChanged { - if (_connectivityResult == null) { - _connectivityResult = StreamController(); - _networkInformation.onchange = allowInterop((_) { - _connectivityResult + if (_connectivityResultStreamController == null) { + _connectivityResultStreamController = + StreamController(); + setProperty(_networkInformation, 'onchange', allowInterop((_) { + _connectivityResultStreamController .add(networkInformationToConnectivityResult(_networkInformation)); - }); + })); + // TODO: Implement the above with _networkInformation.onChange: + // _networkInformation.onChange.listen((_) { + // _connectivityResult + // .add(networkInformationToConnectivityResult(_networkInformation)); + // }); + // Once we can detect when to *cancel* a subscription to the _networkInformation + // onChange Stream upon hot restart. + // https://github.com/dart-lang/sdk/issues/42679 + _connectivityResultStream = + _connectivityResultStreamController.stream.asBroadcastStream(); } - return _connectivityResult.stream; + return _connectivityResultStream; } } diff --git a/packages/connectivity/connectivity_for_web/lib/src/utils/connectivity_result.dart b/packages/connectivity/connectivity_for_web/lib/src/utils/connectivity_result.dart index 28943ef5c7e1..efefd8d52440 100644 --- a/packages/connectivity/connectivity_for_web/lib/src/utils/connectivity_result.dart +++ b/packages/connectivity/connectivity_for_web/lib/src/utils/connectivity_result.dart @@ -1,27 +1,22 @@ +import 'dart:html' as html show NetworkInformation; import 'package:connectivity_platform_interface/connectivity_platform_interface.dart'; /// Converts an incoming NetworkInformation object into the correct ConnectivityResult. -// -// We can't be more specific on the signature of this method because the API is odd, -// data can come from a static value in the DOM, or as the 'target' of a DOM Event. -// -// If we type info as `NetworkInformation`, Dart will complain with: -// "Uncaught Error: Expected a value of type 'NetworkInformation', -// but got one of type 'NetworkInformation'" ConnectivityResult networkInformationToConnectivityResult( - dynamic /* NetworkInformation */ info) { + html.NetworkInformation info, +) { if (info == null) { return ConnectivityResult.none; } if (info.downlink == 0 && info.rtt == 0) { return ConnectivityResult.none; } - if (info.type != null) { - return _typeToConnectivityResult(info.type); - } if (info.effectiveType != null) { return _effectiveTypeToConnectivityResult(info.effectiveType); } + if (info.type != null) { + return _typeToConnectivityResult(info.type); + } return ConnectivityResult.none; } diff --git a/packages/connectivity/connectivity_for_web/pubspec.yaml b/packages/connectivity/connectivity_for_web/pubspec.yaml index e4a1673e40c2..e1142a75c91f 100644 --- a/packages/connectivity/connectivity_for_web/pubspec.yaml +++ b/packages/connectivity/connectivity_for_web/pubspec.yaml @@ -1,6 +1,6 @@ name: connectivity_for_web description: An implementation for the web platform of the Flutter `connectivity` plugin. This uses the NetworkInformation Web API, with a fallback to Navigator.onLine. -version: 0.3.0 +version: 0.3.1 homepage: https://github.com/ditman/plugins/tree/connectivity-web/packages/connectivity/experimental_connectivity_web flutter: @@ -12,7 +12,6 @@ flutter: dependencies: connectivity_platform_interface: ^1.0.3 - js: ^0.6.1+1 flutter_web_plugins: sdk: flutter flutter: @@ -25,6 +24,7 @@ dev_dependencies: flutter_test: sdk: flutter e2e: ^0.2.4+3 + mockito: ^4.1.1 environment: sdk: ">=2.6.0 <3.0.0" diff --git a/packages/connectivity/connectivity_for_web/test/lib/main.dart b/packages/connectivity/connectivity_for_web/test/lib/main.dart index 21621a947ee6..93b9a73cf31b 100644 --- a/packages/connectivity/connectivity_for_web/test/lib/main.dart +++ b/packages/connectivity/connectivity_for_web/test/lib/main.dart @@ -3,6 +3,8 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:connectivity_platform_interface/connectivity_platform_interface.dart'; import 'package:connectivity_for_web/src/network_information_api_connectivity_plugin.dart'; +import 'package:mockito/mockito.dart'; + import 'src/connectivity_mocks.dart'; void main() { @@ -16,11 +18,12 @@ void main() { num rtt = 50, ConnectivityResult expected, }) { - MockNetworkInformation connection = MockNetworkInformation( - type: type, - effectiveType: effectiveType, - downlink: downlink, - rtt: rtt); + final connection = MockNetworkInformation(); + when(connection.type).thenReturn(type); + when(connection.effectiveType).thenReturn(effectiveType); + when(connection.downlink).thenReturn(downlink); + when(connection.rtt).thenReturn(downlink); + NetworkInformationApiConnectivityPlugin plugin = NetworkInformationApiConnectivityPlugin.withConnection(connection); expect(plugin.checkConnectivity(), completion(equals(expected))); @@ -53,16 +56,16 @@ void main() { group('get onConnectivityChanged', () { test('puts change events in a Stream', () async { - MockNetworkInformation connection = - MockNetworkInformation(effectiveType: '4g', downlink: 10, rtt: 50); + final connection = MockNetworkInformation(); NetworkInformationApiConnectivityPlugin plugin = NetworkInformationApiConnectivityPlugin.withConnection(connection); Stream results = plugin.onConnectivityChanged; // Fake a disconnect-reconnect - connection.mockChangeValue(downlink: 0, rtt: 0); - connection.mockChangeValue(downlink: 10, rtt: 50); + await connection.mockChangeValue(downlink: 0, rtt: 0); + await connection.mockChangeValue( + downlink: 10, rtt: 50, effectiveType: '4g'); // The stream of results is infinite, so we need to .take(2) for this test to complete. expect( diff --git a/packages/connectivity/connectivity_for_web/test/lib/src/connectivity_mocks.dart b/packages/connectivity/connectivity_for_web/test/lib/src/connectivity_mocks.dart index 9ce2e811d461..7b82b512065b 100644 --- a/packages/connectivity/connectivity_for_web/test/lib/src/connectivity_mocks.dart +++ b/packages/connectivity/connectivity_for_web/test/lib/src/connectivity_mocks.dart @@ -1,33 +1,12 @@ import 'dart:html'; -import 'package:connectivity_for_web/src/generated/network_information_types.dart' - as dom; +import 'package:mockito/mockito.dart'; /// A Mock implementation of the NetworkInformation API that allows /// for external modification of its values. -class MockNetworkInformation extends dom.NetworkInformation { - @override - String type; - - @override - String effectiveType; - - @override - num downlink; - - @override - num rtt; - - @override - EventListener onchange; - - /// Constructor of mocked instances... - MockNetworkInformation({ - this.type, - this.effectiveType, - this.downlink, - this.rtt, - }); +class MockNetworkInformation extends Mock implements NetworkInformation { + /// The callback that will fire after the network information values change. + Function onchange; /// Changes the desired values, and triggers the change event listener. void mockChangeValue({ @@ -35,26 +14,12 @@ class MockNetworkInformation extends dom.NetworkInformation { String effectiveType, num downlink, num rtt, - }) { - this.type = type ?? this.type; - this.effectiveType = effectiveType ?? this.effectiveType; - this.downlink = downlink ?? this.downlink; - this.rtt = rtt ?? this.rtt; + }) async { + when(this.type).thenAnswer((_) => type); + when(this.effectiveType).thenAnswer((_) => effectiveType); + when(this.downlink).thenAnswer((_) => downlink); + when(this.rtt).thenAnswer((_) => rtt); onchange(Event('change')); } - - @override - void addEventListener(String type, listener, [bool useCapture]) {} - - @override - bool dispatchEvent(Event event) { - return true; - } - - @override - Events get on => null; - - @override - void removeEventListener(String type, listener, [bool useCapture]) {} } diff --git a/packages/connectivity/connectivity_for_web/test/pubspec.yaml b/packages/connectivity/connectivity_for_web/test/pubspec.yaml index 4d7d10a775e2..44f4b552b443 100644 --- a/packages/connectivity/connectivity_for_web/test/pubspec.yaml +++ b/packages/connectivity/connectivity_for_web/test/pubspec.yaml @@ -1,6 +1,6 @@ name: connectivity_web_example description: Example web app for the connectivity plugin -version: 0.1.0 +version: 0.1.1 homepage: https://github.com/flutter/plugins/tree/master/packages/connectivity/connectivity_web dependencies: @@ -18,6 +18,7 @@ dev_dependencies: flutter_driver: sdk: flutter e2e: ^0.2.4+3 + mockito: ^4.1.1 environment: sdk: ">=2.6.0 <3.0.0" diff --git a/packages/connectivity/connectivity_for_web/ts/.gitignore b/packages/connectivity/connectivity_for_web/ts/.gitignore deleted file mode 100644 index de4d1f007dd1..000000000000 --- a/packages/connectivity/connectivity_for_web/ts/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -dist -node_modules diff --git a/packages/connectivity/connectivity_for_web/ts/README.md b/packages/connectivity/connectivity_for_web/ts/README.md deleted file mode 100644 index 3372ad2f3790..000000000000 --- a/packages/connectivity/connectivity_for_web/ts/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# JS Facade generator - -This npm script takes the `network-information-types` npm package, and runs it through Dart's `dart_js_facade_gen` to auto-generate (most) of the JS facades used by this plugin. - -The process is not completely automated yet, but it should be pretty close. - -To generate the facades, and after [installing `npm`](https://www.npmjs.com/get-npm), do: - -``` -npm install -npm run build -``` - -The above will fetch the required dependencies, and generate a `dist/network_information_types.dart` file that you can use with the plugin. - -``` -cp dist/*.dart ../lib/src/generated -``` - -This script should come handy once the Network Information Web API changes, or becomes stable, so the JS-interop part of this plugin can be regenerated more easily. - -Read more: - -* [Dart JS Interop](https://dart.dev/web/js-interop) -* [dart_js_facade_gen](https://www.npmjs.com/package/dart_js_facade_gen) \ No newline at end of file diff --git a/packages/connectivity/connectivity_for_web/ts/package-lock.json b/packages/connectivity/connectivity_for_web/ts/package-lock.json deleted file mode 100644 index 45293a400492..000000000000 --- a/packages/connectivity/connectivity_for_web/ts/package-lock.json +++ /dev/null @@ -1,117 +0,0 @@ -{ - "name": "network-information-types-to-dart-generator", - "version": "1.0.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@types/chai": { - "version": "4.2.9", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.9.tgz", - "integrity": "sha512-NeXgZj+MFL4izGqA4sapdYzkzQG+MtGra9vhQ58dnmDY++VgJaRUws+aLVV5zRJCYJl/8s9IjMmhiUw1WsKSmw==" - }, - "@types/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-UoOfVEzAUpeSPmjm7h1uk5MH6KZma2z2O7a75onTGjnNvAvMVrPzPL/vBbT65iIGHWj6rokwfmYcmxmlSf2uwg==", - "requires": { - "@types/node": "*" - } - }, - "@types/minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=" - }, - "@types/mocha": { - "version": "5.2.7", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz", - "integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==" - }, - "@types/node": { - "version": "12.12.28", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.28.tgz", - "integrity": "sha512-g73GJYJDXgf0jqg+P9S8h2acWbDXNkoCX8DLtJVu7Fkn788pzQ/oJsrdJz/2JejRf/SjfZaAhsw+3nd1D5EWGg==" - }, - "@types/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@types/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LrnsgZIfJaysFkv9rRJp4/uAyqw87oVed3s1hhF83nwbo9c7MG9g5DqR0seHP+lkX4ldmMrVolPjQSe2ZfD0yA==", - "requires": { - "source-map": "*" - } - }, - "@types/source-map-support": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@types/source-map-support/-/source-map-support-0.5.1.tgz", - "integrity": "sha512-VDqnZe9D2zR19qbeRvwYyHSp7AtUtCkTaRVFQ8wzwH9TXw9kKKq/vBhfEnFEXVupO2M0lBMA9mr/XyQ6gEkUOA==", - "requires": { - "@types/node": "*" - } - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" - }, - "dart-style": { - "version": "1.3.2-dev", - "resolved": "https://registry.npmjs.org/dart-style/-/dart-style-1.3.2-dev.tgz", - "integrity": "sha512-NFI4UQYvG32t/cEkQAdkXT2ZT72tjF61tMWoALmnGwj03d2Co94zwGfbnFfdQUQvrhUNx8Wz2jKSVxGrmFaVJQ==" - }, - "dart_js_facade_gen": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/dart_js_facade_gen/-/dart_js_facade_gen-0.0.7.tgz", - "integrity": "sha512-AZiWsccbzhgJWmBjbFTPuvBhwGXk7AN8nOP91/I8PqUfSvVALiWshDc66TvywNkdNogAE5X8zlxjodw1C3iHpA==", - "requires": { - "@types/chai": "^4.2.3", - "@types/fs-extra": "^8.0.0", - "@types/minimist": "^1.2.0", - "@types/mocha": "^5.2.7", - "@types/node": "^12.7.8", - "@types/source-map": "^0.5.7", - "@types/source-map-support": "^0.5.0", - "dart-style": "^1.3.2-dev", - "minimist": "^1.2.0", - "source-map": "^0.7.3", - "source-map-support": "^0.5.13", - "typescript": "^3.6.3" - } - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" - }, - "network-information-types": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/network-information-types/-/network-information-types-0.1.0.tgz", - "integrity": "sha512-cRUCYZoRHTMjYcgk5MbwqM0h0Za34panRxAJKY8n+mQ+NLMuRIw7aKzmaZqkC/cte7bnRcdfTwFA27GgN62EtQ==" - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==" - }, - "source-map-support": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", - "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, - "typescript": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.2.tgz", - "integrity": "sha512-EgOVgL/4xfVrCMbhYKUQTdF37SQn4Iw73H5BgCrF1Abdun7Kwy/QZsE/ssAy0y4LxBbvua3PIbFsbRczWWnDdQ==" - } - } -} diff --git a/packages/connectivity/connectivity_for_web/ts/package.json b/packages/connectivity/connectivity_for_web/ts/package.json deleted file mode 100644 index 665c89d6afbb..000000000000 --- a/packages/connectivity/connectivity_for_web/ts/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "network-information-types-to-dart-generator", - "version": "1.0.0", - "description": "Use dart_js_facade_gen to generate the facade for the network-information-types package.", - "main": "index.js", - "private": true, - "scripts": { - "build": "./scripts/run_facade_gen.sh", - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "", - "license": "MIT", - "dependencies": { - "network-information-types": "0.1.0", - "dart_js_facade_gen": "^0.0.7" - } -} diff --git a/packages/connectivity/connectivity_for_web/ts/scripts/run_facade_gen.sh b/packages/connectivity/connectivity_for_web/ts/scripts/run_facade_gen.sh deleted file mode 100755 index c74b8ba171b2..000000000000 --- a/packages/connectivity/connectivity_for_web/ts/scripts/run_facade_gen.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -INDEX_PATH=node_modules/network-information-types/dist-types/index.d.ts -WORK_PATH=network_information_types.d.ts -DIST_PATH=dist - -# Create dist if it doesn't exist already -mkdir -p $DIST_PATH - -# Copy the input file(s) into our work path -cp $INDEX_PATH $WORK_PATH - -# Run dart_js_facade_gen -dart_js_facade_gen $WORK_PATH --trust-js-types --generate-html --destination . - -# Move output to the right place, and clean after yourself -mv *.dart $DIST_PATH -rm $WORK_PATH