diff --git a/packages/url_launcher/url_launcher_web/CHANGELOG.md b/packages/url_launcher/url_launcher_web/CHANGELOG.md index 0cb57ef924ad..f8416aff9943 100644 --- a/packages/url_launcher/url_launcher_web/CHANGELOG.md +++ b/packages/url_launcher/url_launcher_web/CHANGELOG.md @@ -1,3 +1,7 @@ +# 0.1.1+2 + +- Open urls with target "_top" on iOS PWAs. + # 0.1.1+1 - Make the pedantic dev_dependency explicit. diff --git a/packages/url_launcher/url_launcher_web/lib/src/navigator.dart b/packages/url_launcher/url_launcher_web/lib/src/navigator.dart new file mode 100644 index 000000000000..4c7a99d4c486 --- /dev/null +++ b/packages/url_launcher/url_launcher_web/lib/src/navigator.dart @@ -0,0 +1,15 @@ +@JS() +library navigator; + +import 'package:js/js.dart'; +import 'package:meta/meta.dart'; + +@JS('window.navigator.standalone') +external bool get _standalone; + +/// The window.navigator.standalone DOM property. +bool get standalone => _standalone ?? false; + +@visibleForTesting +@JS('window.navigator.standalone') +external set standalone(bool enabled); diff --git a/packages/url_launcher/url_launcher_web/lib/url_launcher_web.dart b/packages/url_launcher/url_launcher_web/lib/url_launcher_web.dart index c37d8724d2c9..688df43ec84a 100644 --- a/packages/url_launcher/url_launcher_web/lib/url_launcher_web.dart +++ b/packages/url_launcher/url_launcher_web/lib/url_launcher_web.dart @@ -4,6 +4,7 @@ import 'dart:html' as html; import 'package:flutter_web_plugins/flutter_web_plugins.dart'; import 'package:meta/meta.dart'; import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart'; +import 'src/navigator.dart' as navigator; /// The web implementation of [UrlLauncherPlatform]. /// @@ -19,7 +20,10 @@ class UrlLauncherPlugin extends UrlLauncherPlatform { /// Returns the newly created window. @visibleForTesting html.WindowBase openNewWindow(String url) { - return html.window.open(url, ''); + // We need to open on _top in ios browsers in standalone mode. + // See https://github.com/flutter/flutter/issues/51461 for reference. + final target = navigator.standalone ? '_top' : ''; + return html.window.open(url, target); } @override diff --git a/packages/url_launcher/url_launcher_web/pubspec.yaml b/packages/url_launcher/url_launcher_web/pubspec.yaml index 8e7467797f2e..a43a828af253 100644 --- a/packages/url_launcher/url_launcher_web/pubspec.yaml +++ b/packages/url_launcher/url_launcher_web/pubspec.yaml @@ -1,7 +1,7 @@ name: url_launcher_web description: Web platform implementation of url_launcher homepage: https://github.com/flutter/plugins/tree/master/packages/url_launcher/url_launcher_web -version: 0.1.1+1 +version: 0.1.1+2 flutter: plugin: @@ -17,6 +17,7 @@ dependencies: flutter_web_plugins: sdk: flutter meta: ^1.1.7 + js: ^0.6.0 dev_dependencies: flutter_test: diff --git a/packages/url_launcher/url_launcher_web/test/url_launcher_web_test.dart b/packages/url_launcher/url_launcher_web/test/url_launcher_web_test.dart index 3fb9b7884649..87110136072c 100644 --- a/packages/url_launcher/url_launcher_web/test/url_launcher_web_test.dart +++ b/packages/url_launcher/url_launcher_web/test/url_launcher_web_test.dart @@ -5,10 +5,10 @@ @TestOn('chrome') // Uses web-only Flutter SDK import 'dart:html' as html; - import 'package:flutter_test/flutter_test.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher_web/url_launcher_web.dart'; +import 'package:url_launcher_web/src/navigator.dart' as navigator; import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart'; void main() { @@ -54,6 +54,19 @@ void main() { expect(newWindow.opener, equals(html.window)); }); + test('the window that is launched is in the same window', () { + final originalStandalone = navigator.standalone; + // Simulate the navigator is in standalone mode on iOS devices. + // https://developer.mozilla.org/en-US/docs/Web/API/Navigator + navigator.standalone = true; + final UrlLauncherPlugin urlLauncherPlugin = UrlLauncherPlugin(); + final html.WindowBase window = + urlLauncherPlugin.openNewWindow('https://www.google.com'); + expect(window, isNotNull); + expect(window.opener, isNot(equals(html.window))); + navigator.standalone = originalStandalone; + }); + test('does not implement closeWebView()', () { expect(closeWebView(), throwsUnimplementedError); });