Skip to content

Commit 042406d

Browse files
ditmanEgor
authored andcommitted
[connectivity_for_web] Fix JS Interop in release mode. (flutter#2869)
* Switch to dart:html window.navigator.connection instead of package:js JS-interop. * Overwrite connection.onchange instead of listening to connection.onChange Stream (prevents multiple subscriptions after hot-reload). * Cleaned up old code related to generating the JS facade.
1 parent 7cb0e6e commit 042406d

File tree

13 files changed

+61
-337
lines changed

13 files changed

+61
-337
lines changed

packages/connectivity/connectivity_for_web/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.3.1
2+
3+
* Use NetworkInformation API from dart:html, instead of the JS-interop version.
4+
15
## 0.3.0
26

37
* Rename from "experimental_connectivity_web" to "connectivity_for_web", and move to flutter/plugins master.

packages/connectivity/connectivity_for_web/lib/src/generated/network_information_types.dart

Lines changed: 0 additions & 78 deletions
This file was deleted.
Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,29 @@
11
import 'dart:async';
2+
import 'dart:html' as html show window, NetworkInformation;
3+
import 'dart:js';
4+
import 'dart:js_util';
25

36
import 'package:connectivity_platform_interface/connectivity_platform_interface.dart';
47
import 'package:connectivity_for_web/connectivity_for_web.dart';
58
import 'package:flutter/foundation.dart';
6-
import 'package:js/js.dart';
79

8-
import 'generated/network_information_types.dart' as dom;
910
import 'utils/connectivity_result.dart';
1011

1112
/// The web implementation of the ConnectivityPlatform of the Connectivity plugin.
1213
class NetworkInformationApiConnectivityPlugin extends ConnectivityPlugin {
13-
final dom.NetworkInformation _networkInformation;
14+
final html.NetworkInformation _networkInformation;
1415

1516
/// A check to determine if this version of the plugin can be used.
16-
static bool isSupported() => dom.navigator?.connection != null;
17+
static bool isSupported() => html.window.navigator.connection != null;
1718

1819
/// The constructor of the plugin.
1920
NetworkInformationApiConnectivityPlugin()
20-
: this.withConnection(dom.navigator?.connection);
21+
: this.withConnection(html.window.navigator.connection);
2122

2223
/// Creates the plugin, with an override of the NetworkInformation object.
2324
@visibleForTesting
2425
NetworkInformationApiConnectivityPlugin.withConnection(
25-
dom.NetworkInformation connection)
26+
html.NetworkInformation connection)
2627
: _networkInformation = connection;
2728

2829
/// Checks the connection status of the device.
@@ -31,18 +32,30 @@ class NetworkInformationApiConnectivityPlugin extends ConnectivityPlugin {
3132
return networkInformationToConnectivityResult(_networkInformation);
3233
}
3334

34-
StreamController<ConnectivityResult> _connectivityResult;
35+
StreamController<ConnectivityResult> _connectivityResultStreamController;
36+
Stream<ConnectivityResult> _connectivityResultStream;
3537

3638
/// Returns a Stream of ConnectivityResults changes.
3739
@override
3840
Stream<ConnectivityResult> get onConnectivityChanged {
39-
if (_connectivityResult == null) {
40-
_connectivityResult = StreamController<ConnectivityResult>();
41-
_networkInformation.onchange = allowInterop((_) {
42-
_connectivityResult
41+
if (_connectivityResultStreamController == null) {
42+
_connectivityResultStreamController =
43+
StreamController<ConnectivityResult>();
44+
setProperty(_networkInformation, 'onchange', allowInterop((_) {
45+
_connectivityResultStreamController
4346
.add(networkInformationToConnectivityResult(_networkInformation));
44-
});
47+
}));
48+
// TODO: Implement the above with _networkInformation.onChange:
49+
// _networkInformation.onChange.listen((_) {
50+
// _connectivityResult
51+
// .add(networkInformationToConnectivityResult(_networkInformation));
52+
// });
53+
// Once we can detect when to *cancel* a subscription to the _networkInformation
54+
// onChange Stream upon hot restart.
55+
// https://github.com/dart-lang/sdk/issues/42679
56+
_connectivityResultStream =
57+
_connectivityResultStreamController.stream.asBroadcastStream();
4558
}
46-
return _connectivityResult.stream;
59+
return _connectivityResultStream;
4760
}
4861
}

packages/connectivity/connectivity_for_web/lib/src/utils/connectivity_result.dart

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,22 @@
1+
import 'dart:html' as html show NetworkInformation;
12
import 'package:connectivity_platform_interface/connectivity_platform_interface.dart';
23

34
/// Converts an incoming NetworkInformation object into the correct ConnectivityResult.
4-
//
5-
// We can't be more specific on the signature of this method because the API is odd,
6-
// data can come from a static value in the DOM, or as the 'target' of a DOM Event.
7-
//
8-
// If we type info as `NetworkInformation`, Dart will complain with:
9-
// "Uncaught Error: Expected a value of type 'NetworkInformation',
10-
// but got one of type 'NetworkInformation'"
115
ConnectivityResult networkInformationToConnectivityResult(
12-
dynamic /* NetworkInformation */ info) {
6+
html.NetworkInformation info,
7+
) {
138
if (info == null) {
149
return ConnectivityResult.none;
1510
}
1611
if (info.downlink == 0 && info.rtt == 0) {
1712
return ConnectivityResult.none;
1813
}
19-
if (info.type != null) {
20-
return _typeToConnectivityResult(info.type);
21-
}
2214
if (info.effectiveType != null) {
2315
return _effectiveTypeToConnectivityResult(info.effectiveType);
2416
}
17+
if (info.type != null) {
18+
return _typeToConnectivityResult(info.type);
19+
}
2520
return ConnectivityResult.none;
2621
}
2722

packages/connectivity/connectivity_for_web/pubspec.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: connectivity_for_web
22
description: An implementation for the web platform of the Flutter `connectivity` plugin. This uses the NetworkInformation Web API, with a fallback to Navigator.onLine.
3-
version: 0.3.0
3+
version: 0.3.1
44
homepage: https://github.com/ditman/plugins/tree/connectivity-web/packages/connectivity/experimental_connectivity_web
55

66
flutter:
@@ -12,7 +12,6 @@ flutter:
1212

1313
dependencies:
1414
connectivity_platform_interface: ^1.0.3
15-
js: ^0.6.1+1
1615
flutter_web_plugins:
1716
sdk: flutter
1817
flutter:
@@ -25,6 +24,7 @@ dev_dependencies:
2524
flutter_test:
2625
sdk: flutter
2726
e2e: ^0.2.4+3
27+
mockito: ^4.1.1
2828

2929
environment:
3030
sdk: ">=2.6.0 <3.0.0"

packages/connectivity/connectivity_for_web/test/lib/main.dart

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import 'package:flutter_test/flutter_test.dart';
33
import 'package:connectivity_platform_interface/connectivity_platform_interface.dart';
44
import 'package:connectivity_for_web/src/network_information_api_connectivity_plugin.dart';
55

6+
import 'package:mockito/mockito.dart';
7+
68
import 'src/connectivity_mocks.dart';
79

810
void main() {
@@ -16,11 +18,12 @@ void main() {
1618
num rtt = 50,
1719
ConnectivityResult expected,
1820
}) {
19-
MockNetworkInformation connection = MockNetworkInformation(
20-
type: type,
21-
effectiveType: effectiveType,
22-
downlink: downlink,
23-
rtt: rtt);
21+
final connection = MockNetworkInformation();
22+
when(connection.type).thenReturn(type);
23+
when(connection.effectiveType).thenReturn(effectiveType);
24+
when(connection.downlink).thenReturn(downlink);
25+
when(connection.rtt).thenReturn(downlink);
26+
2427
NetworkInformationApiConnectivityPlugin plugin =
2528
NetworkInformationApiConnectivityPlugin.withConnection(connection);
2629
expect(plugin.checkConnectivity(), completion(equals(expected)));
@@ -53,16 +56,16 @@ void main() {
5356

5457
group('get onConnectivityChanged', () {
5558
test('puts change events in a Stream', () async {
56-
MockNetworkInformation connection =
57-
MockNetworkInformation(effectiveType: '4g', downlink: 10, rtt: 50);
59+
final connection = MockNetworkInformation();
5860
NetworkInformationApiConnectivityPlugin plugin =
5961
NetworkInformationApiConnectivityPlugin.withConnection(connection);
6062

6163
Stream<ConnectivityResult> results = plugin.onConnectivityChanged;
6264

6365
// Fake a disconnect-reconnect
64-
connection.mockChangeValue(downlink: 0, rtt: 0);
65-
connection.mockChangeValue(downlink: 10, rtt: 50);
66+
await connection.mockChangeValue(downlink: 0, rtt: 0);
67+
await connection.mockChangeValue(
68+
downlink: 10, rtt: 50, effectiveType: '4g');
6669

6770
// The stream of results is infinite, so we need to .take(2) for this test to complete.
6871
expect(
Lines changed: 9 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,25 @@
11
import 'dart:html';
22

3-
import 'package:connectivity_for_web/src/generated/network_information_types.dart'
4-
as dom;
3+
import 'package:mockito/mockito.dart';
54

65
/// A Mock implementation of the NetworkInformation API that allows
76
/// for external modification of its values.
8-
class MockNetworkInformation extends dom.NetworkInformation {
9-
@override
10-
String type;
11-
12-
@override
13-
String effectiveType;
14-
15-
@override
16-
num downlink;
17-
18-
@override
19-
num rtt;
20-
21-
@override
22-
EventListener onchange;
23-
24-
/// Constructor of mocked instances...
25-
MockNetworkInformation({
26-
this.type,
27-
this.effectiveType,
28-
this.downlink,
29-
this.rtt,
30-
});
7+
class MockNetworkInformation extends Mock implements NetworkInformation {
8+
/// The callback that will fire after the network information values change.
9+
Function onchange;
3110

3211
/// Changes the desired values, and triggers the change event listener.
3312
void mockChangeValue({
3413
String type,
3514
String effectiveType,
3615
num downlink,
3716
num rtt,
38-
}) {
39-
this.type = type ?? this.type;
40-
this.effectiveType = effectiveType ?? this.effectiveType;
41-
this.downlink = downlink ?? this.downlink;
42-
this.rtt = rtt ?? this.rtt;
17+
}) async {
18+
when(this.type).thenAnswer((_) => type);
19+
when(this.effectiveType).thenAnswer((_) => effectiveType);
20+
when(this.downlink).thenAnswer((_) => downlink);
21+
when(this.rtt).thenAnswer((_) => rtt);
4322

4423
onchange(Event('change'));
4524
}
46-
47-
@override
48-
void addEventListener(String type, listener, [bool useCapture]) {}
49-
50-
@override
51-
bool dispatchEvent(Event event) {
52-
return true;
53-
}
54-
55-
@override
56-
Events get on => null;
57-
58-
@override
59-
void removeEventListener(String type, listener, [bool useCapture]) {}
6025
}

packages/connectivity/connectivity_for_web/test/pubspec.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: connectivity_web_example
22
description: Example web app for the connectivity plugin
3-
version: 0.1.0
3+
version: 0.1.1
44
homepage: https://github.com/flutter/plugins/tree/master/packages/connectivity/connectivity_web
55

66
dependencies:
@@ -18,6 +18,7 @@ dev_dependencies:
1818
flutter_driver:
1919
sdk: flutter
2020
e2e: ^0.2.4+3
21+
mockito: ^4.1.1
2122

2223
environment:
2324
sdk: ">=2.6.0 <3.0.0"

packages/connectivity/connectivity_for_web/ts/.gitignore

Lines changed: 0 additions & 2 deletions
This file was deleted.

packages/connectivity/connectivity_for_web/ts/README.md

Lines changed: 0 additions & 25 deletions
This file was deleted.

0 commit comments

Comments
 (0)