[url_launcher_web] migrate to pkg:web (#5451)

Require the latest Flutter/Dart SDKs
Enables use via wasm
Related to https://github.com/flutter/flutter/issues/117022
This commit is contained in:
Kevin Moore
2023-11-21 12:21:04 -08:00
committed by GitHub
parent c9933fc09a
commit 4be0de6a41
9 changed files with 59 additions and 1549 deletions

View File

@ -1,3 +1,8 @@
## 2.2.1
* Supports Flutter Web + Wasm
* Updates minimum supported SDK version to Flutter 3.16.0/Dart 3.2.0.
## 2.2.0 ## 2.2.0
* Implements `supportsMode` and `supportsCloseForMode`. * Implements `supportsMode` and `supportsCloseForMode`.

View File

@ -1,10 +0,0 @@
targets:
$default:
sources:
- integration_test/*.dart
- lib/$lib$
- $package$
builders:
mockito|mockBuilder:
generate_for:
- integration_test/**

View File

@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:html' as html;
import 'dart:js_util'; import 'dart:js_util';
import 'dart:ui_web' as ui_web; import 'dart:ui_web' as ui_web;
@ -11,6 +10,7 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart'; import 'package:integration_test/integration_test.dart';
import 'package:url_launcher_platform_interface/link.dart'; import 'package:url_launcher_platform_interface/link.dart';
import 'package:url_launcher_web/src/link.dart'; import 'package:url_launcher_web/src/link.dart';
import 'package:web/helpers.dart' as html;
void main() { void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized(); IntegrationTestWidgetsFlutterBinding.ensureInitialized();
@ -174,7 +174,9 @@ void main() {
html.Element _findSingleAnchor() { html.Element _findSingleAnchor() {
final List<html.Element> foundAnchors = <html.Element>[]; final List<html.Element> foundAnchors = <html.Element>[];
for (final html.Element anchor in html.document.querySelectorAll('a')) { html.NodeList anchors = html.document.querySelectorAll('a');
for (int i = 0; i < anchors.length; i++) {
final html.Element anchor = anchors.item(i)! as html.Element;
if (hasProperty(anchor, linkViewIdProperty)) { if (hasProperty(anchor, linkViewIdProperty)) {
foundAnchors.add(anchor); foundAnchors.add(anchor);
} }
@ -184,7 +186,9 @@ html.Element _findSingleAnchor() {
final html.ShadowRoot? shadowRoot = final html.ShadowRoot? shadowRoot =
html.document.querySelector('flt-glass-pane')?.shadowRoot; html.document.querySelector('flt-glass-pane')?.shadowRoot;
if (shadowRoot != null) { if (shadowRoot != null) {
for (final html.Element anchor in shadowRoot.querySelectorAll('a')) { anchors = shadowRoot.querySelectorAll('a');
for (int i = 0; i < anchors.length; i++) {
final html.Element anchor = anchors.item(i)! as html.Element;
if (hasProperty(anchor, linkViewIdProperty)) { if (hasProperty(anchor, linkViewIdProperty)) {
foundAnchors.add(anchor); foundAnchors.add(anchor);
} }

View File

@ -2,18 +2,31 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:html' as html; import 'dart:js_interop';
import 'dart:js_util';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart'; import 'package:integration_test/integration_test.dart';
import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart' show any, verify, when, Mock;
import 'package:mockito/mockito.dart';
import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart'; import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart';
import 'package:url_launcher_web/url_launcher_web.dart'; import 'package:url_launcher_web/url_launcher_web.dart';
import 'package:web/helpers.dart' as html;
import 'url_launcher_web_test.mocks.dart'; abstract class MyWindow {
html.Window? open(Object? a, Object? b, Object? c);
html.Navigator? get navigator;
}
@JSExport()
class MockWindow extends Mock implements MyWindow {}
abstract class MyNavigator {
String? get userAgent;
}
@JSExport()
class MockNavigator extends Mock implements MyNavigator {}
@GenerateMocks(<Type>[html.Window, html.Navigator])
void main() { void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized(); IntegrationTestWidgetsFlutterBinding.ensureInitialized();
@ -26,15 +39,21 @@ void main() {
setUp(() { setUp(() {
mockWindow = MockWindow(); mockWindow = MockWindow();
mockNavigator = MockNavigator(); mockNavigator = MockNavigator();
when(mockWindow.navigator).thenReturn(mockNavigator);
final html.Window jsMockWindow =
createDartExport(mockWindow) as html.Window;
final html.Navigator jsMockNavigator =
createDartExport(mockNavigator) as html.Navigator;
when(mockWindow.navigator).thenReturn(jsMockNavigator);
// Simulate that window.open does something. // Simulate that window.open does something.
when(mockWindow.open(any, any, any)).thenReturn(MockWindow()); when(mockWindow.open(any, any, any)).thenReturn(jsMockWindow);
when(mockNavigator.userAgent).thenReturn( when(mockNavigator.userAgent).thenReturn(
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'); 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36');
plugin = UrlLauncherPlugin(debugWindow: mockWindow); plugin = UrlLauncherPlugin(debugWindow: mockWindow as html.Window);
}); });
group('canLaunch', () { group('canLaunch', () {
@ -43,8 +62,7 @@ void main() {
}); });
testWidgets('"https" URLs -> true', (WidgetTester _) async { testWidgets('"https" URLs -> true', (WidgetTester _) async {
expect( expect(plugin.canLaunch('https://google.com'), completion(isTrue));
plugin.canLaunch('https://go, (Widogle.com'), completion(isTrue));
}); });
testWidgets('"mailto" URLs -> true', (WidgetTester _) async { testWidgets('"mailto" URLs -> true', (WidgetTester _) async {
@ -167,7 +185,7 @@ void main() {
when(mockNavigator.userAgent).thenReturn( when(mockNavigator.userAgent).thenReturn(
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5.1 Safari/605.1.15'); 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5.1 Safari/605.1.15');
// Recreate the plugin, so it grabs the overrides from this group // Recreate the plugin, so it grabs the overrides from this group
plugin = UrlLauncherPlugin(debugWindow: mockWindow); plugin = UrlLauncherPlugin(debugWindow: mockWindow as html.Window);
}); });
testWidgets('http urls should be launched in a new window', testWidgets('http urls should be launched in a new window',

View File

@ -2,20 +2,20 @@ name: regular_integration_tests
publish_to: none publish_to: none
environment: environment:
sdk: ">=3.1.0 <4.0.0" sdk: ^3.2.0
flutter: ">=3.13.0" flutter: ">=3.16.0"
dependencies: dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
dev_dependencies: dev_dependencies:
build_runner: ^2.1.1
flutter_test: flutter_test:
sdk: flutter sdk: flutter
integration_test: integration_test:
sdk: flutter sdk: flutter
mockito: 5.4.1 mockito: 5.4.3
url_launcher_platform_interface: ^2.2.0 url_launcher_platform_interface: ^2.2.0
url_launcher_web: url_launcher_web:
path: ../ path: ../
web: '>=0.3.0 <0.5.0'

View File

@ -3,7 +3,6 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:async'; import 'dart:async';
import 'dart:html' as html;
import 'dart:js_util'; import 'dart:js_util';
import 'dart:ui_web' as ui_web; import 'dart:ui_web' as ui_web;
@ -13,6 +12,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:url_launcher_platform_interface/link.dart'; import 'package:url_launcher_platform_interface/link.dart';
import 'package:web/helpers.dart' as html;
/// The unique identifier for the view type to be used for link platform views. /// The unique identifier for the view type to be used for link platform views.
const String linkViewType = '__url_launcher::link'; const String linkViewType = '__url_launcher::link';
@ -104,7 +104,11 @@ class LinkViewController extends PlatformViewController {
if (_instances.isEmpty) { if (_instances.isEmpty) {
// This is the first controller being created, attach the global click // This is the first controller being created, attach the global click
// listener. // listener.
_clickSubscription = html.window.onClick.listen(_onGlobalClick);
_clickSubscription =
const html.EventStreamProvider<html.MouseEvent>('click')
.forTarget(html.window)
.listen(_onGlobalClick);
} }
_instances[viewId] = this; _instances[viewId] = this;
} }
@ -164,10 +168,10 @@ class LinkViewController extends PlatformViewController {
@override @override
final int viewId; final int viewId;
late html.Element _element; late html.HTMLElement _element;
Future<void> _initialize() async { Future<void> _initialize() async {
_element = html.Element.tag('a'); _element = html.document.createElement('a') as html.HTMLElement;
setProperty(_element, linkViewIdProperty, viewId); setProperty(_element, linkViewIdProperty, viewId);
_element.style _element.style
..opacity = '0' ..opacity = '0'

View File

@ -3,13 +3,13 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:async'; import 'dart:async';
import 'dart:html' as html;
import 'dart:ui_web' as ui_web; import 'dart:ui_web' as ui_web;
import 'package:flutter/foundation.dart' show kDebugMode, visibleForTesting; import 'package:flutter/foundation.dart' show kDebugMode, visibleForTesting;
import 'package:flutter_web_plugins/flutter_web_plugins.dart' show Registrar; import 'package:flutter_web_plugins/flutter_web_plugins.dart' show Registrar;
import 'package:url_launcher_platform_interface/link.dart'; import 'package:url_launcher_platform_interface/link.dart';
import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart'; import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart';
import 'package:web/web.dart' as html;
import 'src/link.dart'; import 'src/link.dart';
@ -68,7 +68,7 @@ class UrlLauncherPlugin extends UrlLauncherPlatform {
/// ///
/// Returns the newly created window. /// Returns the newly created window.
@visibleForTesting @visibleForTesting
html.WindowBase? openNewWindow(String url, {String? webOnlyWindowName}) { html.Window? openNewWindow(String url, {String? webOnlyWindowName}) {
final String? scheme = _getUrlScheme(url); final String? scheme = _getUrlScheme(url);
// Actively disallow opening some schemes, like javascript. // Actively disallow opening some schemes, like javascript.
// See https://github.com/flutter/flutter/issues/136657 // See https://github.com/flutter/flutter/issues/136657

View File

@ -2,11 +2,11 @@ name: url_launcher_web
description: Web platform implementation of url_launcher description: Web platform implementation of url_launcher
repository: https://github.com/flutter/packages/tree/main/packages/url_launcher/url_launcher_web repository: https://github.com/flutter/packages/tree/main/packages/url_launcher/url_launcher_web
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+url_launcher%22 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+url_launcher%22
version: 2.2.0 version: 2.2.1
environment: environment:
sdk: ">=3.1.0 <4.0.0" sdk: ^3.2.0
flutter: ">=3.13.0" flutter: ">=3.16.0"
flutter: flutter:
plugin: plugin:
@ -22,6 +22,7 @@ dependencies:
flutter_web_plugins: flutter_web_plugins:
sdk: flutter sdk: flutter
url_launcher_platform_interface: ^2.2.0 url_launcher_platform_interface: ^2.2.0
web: '>=0.3.0 <0.5.0'
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: