[url_launcher] Remove renderView usage (#6137)

Removes calls to the deprecated `renderView` method, replacing them with best-effort lookup of the implicit view. This only affects an API that has been deprecated for almost two years, and only when using a specific optional parameter on that method, so the potential impact here is minimal, and this avoids the need for a breaking change.

In the future, when we remove this deprecated API, the workaround will go away as well.

Also opportunistically removes `_ambiguate` and `_anonymize` as they were only needed for versions of Flutter we no longer support.

Fixes https://github.com/flutter/flutter/issues/143449
This commit is contained in:
stuartmorgan
2024-02-21 10:12:07 -08:00
committed by GitHub
parent e88ca69b5d
commit 5f44e3db01
4 changed files with 48 additions and 33 deletions

View File

@ -1,3 +1,7 @@
## 6.2.5
* Removes use of deprecated `renderView` API.
## 6.2.4
* Updates support matrix in README to indicate that iOS 11 is no longer supported.

View File

@ -3,8 +3,10 @@
// found in the LICENSE file.
import 'dart:async';
import 'dart:ui';
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart';
@ -85,15 +87,14 @@ Future<bool> launch(
/// [true] so that ui is automatically computed if [statusBarBrightness] is set.
bool previousAutomaticSystemUiAdjustment = true;
if (statusBarBrightness != null &&
defaultTargetPlatform == TargetPlatform.iOS &&
_ambiguate(WidgetsBinding.instance) != null) {
previousAutomaticSystemUiAdjustment = _ambiguate(WidgetsBinding.instance)!
.renderView
.automaticSystemUiAdjustment;
_ambiguate(WidgetsBinding.instance)!
.renderView
.automaticSystemUiAdjustment = false;
final RenderView? renderViewToAdjust =
statusBarBrightness != null && defaultTargetPlatform == TargetPlatform.iOS
? _findImplicitRenderView()
: null;
if (renderViewToAdjust != null) {
previousAutomaticSystemUiAdjustment =
renderViewToAdjust.automaticSystemUiAdjustment;
renderViewToAdjust.automaticSystemUiAdjustment = false;
SystemChrome.setSystemUIOverlayStyle(statusBarBrightness == Brightness.light
? SystemUiOverlayStyle.dark
: SystemUiOverlayStyle.light);
@ -110,11 +111,9 @@ Future<bool> launch(
webOnlyWindowName: webOnlyWindowName,
);
if (statusBarBrightness != null &&
_ambiguate(WidgetsBinding.instance) != null) {
_ambiguate(WidgetsBinding.instance)!
.renderView
.automaticSystemUiAdjustment = previousAutomaticSystemUiAdjustment;
if (renderViewToAdjust != null) {
renderViewToAdjust.automaticSystemUiAdjustment =
previousAutomaticSystemUiAdjustment;
}
return result;
@ -146,8 +145,22 @@ Future<void> closeWebView() async {
return UrlLauncherPlatform.instance.closeWebView();
}
/// This allows a value of type T or T? to be treated as a value of type T?.
/// Returns the [RenderView] associated with the implicit [FlutterView], if any.
///
/// We use this so that APIs that have become non-nullable can still be used
/// with `!` and `?` on the stable branch.
T? _ambiguate<T>(T? value) => value;
/// [launch] predates multi-window support, and it doesn't have enough context
/// to get the right render view, so this assumes anyone still trying to use
/// the deprecated API with `statusBarBrightness` is in a single-view scenario.
/// This allows a best-effort implementation of the deprecated API for as long
/// as it continues to exist, without depending on deprecated Flutter APIs (and
/// therefore keeping url_launcher forward-compatible with future versions of
/// Flutter for longer).
RenderView? _findImplicitRenderView() {
final FlutterView? implicitFlutterView =
WidgetsBinding.instance.platformDispatcher.implicitView;
if (implicitFlutterView == null) {
return null;
}
return WidgetsBinding.instance.renderViews
.where((RenderView v) => v.flutterView == implicitFlutterView)
.firstOrNull;
}

View File

@ -3,11 +3,11 @@ description: Flutter plugin for launching a URL. Supports
web, phone, SMS, and email schemes.
repository: https://github.com/flutter/packages/tree/main/packages/url_launcher/url_launcher
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+url_launcher%22
version: 6.2.4
version: 6.2.5
environment:
sdk: ">=3.1.0 <4.0.0"
flutter: ">=3.13.0"
sdk: ">=3.2.0 <4.0.0"
flutter: ">=3.16.0"
flutter:
plugin:

View File

@ -235,10 +235,11 @@ void main() {
..setResponse(true);
final TestWidgetsFlutterBinding binding =
_anonymize(TestWidgetsFlutterBinding.ensureInitialized())!
as TestWidgetsFlutterBinding;
TestWidgetsFlutterBinding.ensureInitialized();
debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
final RenderView renderView = binding.renderView;
final RenderView renderView =
RenderView(view: binding.platformDispatcher.implicitView!);
binding.addRenderView(renderView);
renderView.automaticSystemUiAdjustment = true;
final Future<bool> launchResult =
launch('http://flutter.dev/', statusBarBrightness: Brightness.dark);
@ -248,6 +249,7 @@ void main() {
expect(renderView.automaticSystemUiAdjustment, isFalse);
await launchResult;
expect(renderView.automaticSystemUiAdjustment, isTrue);
binding.removeRenderView(renderView);
});
test('sets automaticSystemUiAdjustment to not be null', () async {
@ -265,10 +267,11 @@ void main() {
..setResponse(true);
final TestWidgetsFlutterBinding binding =
_anonymize(TestWidgetsFlutterBinding.ensureInitialized())!
as TestWidgetsFlutterBinding;
TestWidgetsFlutterBinding.ensureInitialized();
debugDefaultTargetPlatformOverride = TargetPlatform.android;
final RenderView renderView = binding.renderView;
final RenderView renderView =
RenderView(view: binding.platformDispatcher.implicitView!);
binding.addRenderView(renderView);
expect(renderView.automaticSystemUiAdjustment, true);
final Future<bool> launchResult =
launch('http://flutter.dev/', statusBarBrightness: Brightness.dark);
@ -278,6 +281,7 @@ void main() {
expect(renderView.automaticSystemUiAdjustment, true);
await launchResult;
expect(renderView.automaticSystemUiAdjustment, true);
binding.removeRenderView(renderView);
});
test('open non-parseable url', () async {
@ -317,9 +321,3 @@ void main() {
});
});
}
/// This removes the type information from a value so that it can be cast
/// to another type even if that cast is redundant.
/// We use this so that APIs whose type have become more descriptive can still
/// be used on the stable branch where they require a cast.
Object? _anonymize<T>(T? value) => value;