Make the App's title optional on web (#152003)

Title (in web) results in updating the [title element][1] which is  a global property. This is problematic in embedded and multiview modes as title should be managed by host apps. This PR makes the title optional, hence if not provided it won't result in the website title being updated.
This commit is contained in:
Juanjo Tugores 2024-08-02 13:00:43 -07:00 committed by GitHub
parent b7997cba54
commit af834eed23
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 29 additions and 11 deletions

View File

@ -166,7 +166,7 @@ class CupertinoApp extends StatefulWidget {
this.onNavigationNotification,
List<NavigatorObserver> this.navigatorObservers = const <NavigatorObserver>[],
this.builder,
this.title = '',
this.title,
this.onGenerateTitle,
this.color,
this.locale,
@ -207,7 +207,7 @@ class CupertinoApp extends StatefulWidget {
this.routerConfig,
this.theme,
this.builder,
this.title = '',
this.title,
this.onGenerateTitle,
this.onNavigationNotification,
this.color,
@ -303,7 +303,7 @@ class CupertinoApp extends StatefulWidget {
/// {@macro flutter.widgets.widgetsApp.title}
///
/// This value is passed unmodified to [WidgetsApp.title].
final String title;
final String? title;
/// {@macro flutter.widgets.widgetsApp.onGenerateTitle}
///

View File

@ -275,7 +275,7 @@ class MaterialApp extends StatefulWidget {
this.routerConfig,
this.backButtonDispatcher,
this.builder,
this.title = '',
this.title,
this.onGenerateTitle,
this.onNavigationNotification,
this.color,
@ -386,7 +386,7 @@ class MaterialApp extends StatefulWidget {
/// {@macro flutter.widgets.widgetsApp.title}
///
/// This value is passed unmodified to [WidgetsApp.title].
final String title;
final String? title;
/// {@macro flutter.widgets.widgetsApp.onGenerateTitle}
///

View File

@ -328,7 +328,7 @@ class WidgetsApp extends StatefulWidget {
this.home,
Map<String, WidgetBuilder> this.routes = const <String, WidgetBuilder>{},
this.builder,
this.title = '',
this.title,
this.onGenerateTitle,
this.textStyle,
required this.color,
@ -425,7 +425,7 @@ class WidgetsApp extends StatefulWidget {
this.routerConfig,
this.backButtonDispatcher,
this.builder,
this.title = '',
this.title,
this.onGenerateTitle,
this.onNavigationNotification,
this.textStyle,
@ -828,7 +828,7 @@ class WidgetsApp extends StatefulWidget {
///
/// To provide a localized title instead, use [onGenerateTitle].
/// {@endtemplate}
final String title;
final String? title;
/// {@template flutter.widgets.widgetsApp.onGenerateTitle}
/// If non-null this callback function is called to produce the app's
@ -1771,7 +1771,7 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
return true;
}());
final Widget title;
final Widget? title;
if (widget.onGenerateTitle != null) {
title = Builder(
// This Builder exists to provide a context below the Localizations widget.
@ -1786,9 +1786,14 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
);
},
);
} else if (widget.title == null && kIsWeb) {
// Updating the <title /> element in the DOM is problematic in embedded
// and multiview modes as title should be managed by host apps.
// Refer to https://github.com/flutter/flutter/pull/152003 for more info.
title = null;
} else {
title = Title(
title: widget.title,
title: widget.title ?? '',
color: widget.color.withOpacity(1.0),
child: result,
);
@ -1823,7 +1828,7 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
child: Localizations(
locale: appLocale,
delegates: _localizationsDelegates.toList(),
child: title,
child: title ?? result,
),
),
),

View File

@ -70,6 +70,7 @@ void main() {
);
await tester.pumpWidget(const CupertinoApp(
theme: CupertinoThemeData(brightness: Brightness.light),
title: '',
color: dynamicColor,
home: Placeholder(),
));
@ -79,6 +80,7 @@ void main() {
await tester.pumpWidget(const CupertinoApp(
theme: CupertinoThemeData(brightness: Brightness.dark),
color: dynamicColor,
title: '',
home: Placeholder(),
));

View File

@ -153,6 +153,17 @@ void main() {
expect(checked, isTrue);
}, variant: KeySimulatorTransitModeVariant.all());
testWidgets('Title is not created if title is not passed and kIsweb', (WidgetTester tester) async {
await tester.pumpWidget(
WidgetsApp(
color: const Color(0xFF123456),
builder: (BuildContext context, Widget? child) => Container(),
),
);
expect(find.byType(Title), kIsWeb ? findsNothing : findsOneWidget);
});
group('error control test', () {
Future<void> expectFlutterError({
required GlobalKey<NavigatorState> key,