Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Inspector V2] Enable Inspector V2 by default #8650

Merged
merged 12 commits into from
Jan 6, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -94,19 +94,6 @@ class SettingsDialog extends StatelessWidget {
gaItem: gac.wasm,
),
),
// TODO(https://github.com/flutter/devtools/issues/7860): Clean-up
// after Inspector V2 has been released.
if (FeatureFlags.inspectorV2)
Flexible(
child: CheckboxSetting(
notifier:
preferences.inspector.inspectorV2Enabled
as ValueNotifier<bool?>,
title: 'Enable the new Inspector',
description: 'Try out the redesigned Flutter Inspector.',
gaItem: gac.inspectorV2Enabled,
),
),
],
const SizedBox(height: largeSpacing),
...dialogSubHeader(theme, 'Troubleshooting'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,23 +58,6 @@ class InspectorControls extends StatelessWidget {
ShowImplementationWidgetsButton(controller: controller!),
],
const Spacer(),
// TODO(https://github.com/flutter/devtools/issues/7860): Clean-up after
// Inspector V2 has been released.
if (FeatureFlags.inspectorV2) ...[
const SizedBox(width: defaultSpacing),
SwitchSetting(
notifier:
preferences.inspector.inspectorV2Enabled as ValueNotifier<bool>,
title: 'New Inspector',
tooltip: 'Try out the redesigned Flutter Inspector.',
gaScreen: gac.inspector,
gaItem: gac.inspectorV2Enabled,
activeColor: activeButtonColor,
inactiveColor: Colors.transparent,
minScreenWidthForTextBeforeScaling:
minScreenWidthForTextBeforeScaling,
),
],
const SizedBox(width: defaultSpacing),
const InspectorServiceExtensionButtonGroup(),
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,30 +52,33 @@ class _InspectorScreenSwitcherState extends State<InspectorScreenSwitcher>
> {
bool get shouldShowInspectorV2 =>
FeatureFlags.inspectorV2 &&
preferences.inspector.inspectorV2Enabled.value;
!preferences.inspector.legacyInspectorEnabled.value;

@override
void didChangeDependencies() {
super.didChangeDependencies();
if (!initController()) return;

addAutoDisposeListener(preferences.inspector.inspectorV2Enabled, () async {
controller.legacyInspectorController.setVisibleToUser(
!shouldShowInspectorV2,
);
await controller.v2InspectorController.setVisibleToUser(
shouldShowInspectorV2,
);
});
addAutoDisposeListener(
preferences.inspector.legacyInspectorEnabled,
() async {
controller.legacyInspectorController.setVisibleToUser(
!shouldShowInspectorV2,
);
await controller.v2InspectorController.setVisibleToUser(
shouldShowInspectorV2,
);
},
);
}

@override
Widget build(BuildContext context) {
final controller = Provider.of<InspectorScreenController>(context);

return ValueListenableBuilder(
valueListenable: preferences.inspector.inspectorV2Enabled,
builder: (context, v2Enabled, _) {
valueListenable: preferences.inspector.legacyInspectorEnabled,
builder: (context, _, _) {
if (shouldShowInspectorV2) {
return v2.InspectorScreenBody(
controller: controller.v2InspectorController,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'package:vm_service/vm_service.dart' hide Stack;

import '../../shared/analytics/analytics.dart' as ga;
import '../../shared/analytics/constants.dart' as gac;
import '../../shared/feature_flags.dart';
import '../../shared/globals.dart';
import '../../shared/preferences/preferences.dart';
import '../../shared/primitives/simple_items.dart';
Expand All @@ -25,8 +26,9 @@ class FlutterInspectorSettingsDialog extends StatelessWidget {
final dialogHeight = scaleByFontFactor(500.0);

return ValueListenableBuilder(
valueListenable: preferences.inspector.inspectorV2Enabled,
builder: (context, inspectorV2Enabled, _) {
valueListenable: preferences.inspector.legacyInspectorEnabled,
builder: (context, legacyInspectorEnabled, _) {
final inspectorV2Enabled = !legacyInspectorEnabled;
return DevToolsDialog(
title: const DialogTitleText('Flutter Inspector Settings'),
content: SizedBox(
Expand Down Expand Up @@ -61,6 +63,22 @@ class FlutterInspectorSettingsDialog extends StatelessWidget {
const InspectorDefaultDetailsViewOption(),
],
const SizedBox(height: largeSpacing),
// TODO(https://github.com/flutter/devtools/issues/7860): Clean-up
// after Inspector V2 has been released.
if (FeatureFlags.inspectorV2)
Flexible(
child: CheckboxSetting(
notifier:
preferences.inspector.legacyInspectorEnabled
as ValueNotifier<bool?>,
title: 'Use legacy inspector',
description:
'Disable the redesigned Flutter inspector. Please know that '
'the legacy inspector may be removed in a future release.',
gaItem: gac.inspectorV2Enabled,
),
),
const SizedBox(height: largeSpacing),
...dialogSubHeader(theme, 'Package Directories'),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import '../../shared/analytics/analytics.dart' as ga;
import '../../shared/analytics/constants.dart' as gac;
import '../../shared/console/eval/inspector_tree_v2.dart';
import '../../shared/globals.dart';
import '../../shared/managers/banner_messages.dart';
import '../../shared/managers/error_badge_manager.dart';
import '../../shared/primitives/blocking_action_mixin.dart';
import '../../shared/ui/common_widgets.dart';
Expand Down Expand Up @@ -57,6 +58,8 @@ class InspectorScreenBodyState extends State<InspectorScreenBody>
static const inspectorTreeKey = Key('Inspector Tree');
static const minScreenWidthForTextBeforeScaling = 900.0;

static const _welcomeShownStorageId = 'inspectorV2WelcomeShown';

@override
void dispose() {
_inspectorTreeController.dispose();
Expand All @@ -70,7 +73,7 @@ class InspectorScreenBodyState extends State<InspectorScreenBody>
}

@override
void didChangeDependencies() {
void didChangeDependencies() async {
super.didChangeDependencies();

if (serviceConnection.inspectorService == null) {
Expand Down Expand Up @@ -112,6 +115,12 @@ class InspectorScreenBodyState extends State<InspectorScreenBody>
}

_inspectorTreeController.setSearchTarget(searchTarget);

unawaited(
_maybeShowWelcomeMessage(context).catchError((_) {
// Ignore errors.
}),
);
}

@override
Expand Down Expand Up @@ -217,6 +226,16 @@ class InspectorScreenBodyState extends State<InspectorScreenBody>
}),
);
}

Future<void> _maybeShowWelcomeMessage(BuildContext context) async {
final welcomeAlreadyShown = await storage.getValue(_welcomeShownStorageId);
if (welcomeAlreadyShown == 'true') return;
// Mark the welcome message as shown.
await storage.setValue(_welcomeShownStorageId, 'true');
if (context.mounted) {
pushWelcomeToNewInspectorMessage(context, InspectorScreen.id);
}
}
}

class InspectorTreeControls extends StatelessWidget {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ const verboseLogging = 'verboseLogging';
const inspectorHoverEvalMode = 'inspectorHoverEvalMode';
const inspectorV2Enabled = 'inspectorV2Enabled';
const inspectorAutoRefreshEnabled = 'inspectorAutoRefreshEnabled';
const inspectorV2Docs = 'inspectorV2Docs';
const clearLogs = 'clearLogs';
const copyLogs = 'copyLogs';

Expand Down
111 changes: 86 additions & 25 deletions packages/devtools_app/lib/src/shared/managers/banner_messages.dart
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,8 @@ class BannerMessages extends StatelessWidget {
// TODO(kenz): add an 'info' type.
enum BannerMessageType {
warning,
error;
error,
info;

static BannerMessageType? parse(String? value) {
for (final type in BannerMessageType.values) {
Expand All @@ -164,11 +165,11 @@ class BannerMessage extends StatelessWidget {
Widget build(BuildContext context) {
final theme = Theme.of(context);
final colorScheme = theme.colorScheme;
final backgroundColor = _backgroundColor(colorScheme);
final foregroundColor = _foregroundColor(colorScheme);

return Card(
color:
messageType == BannerMessageType.error
? colorScheme.errorContainer
: colorScheme.warningContainer,
color: backgroundColor,
margin: const EdgeInsets.only(bottom: intermediateSpacing),
child: Padding(
padding: const EdgeInsets.symmetric(
Expand All @@ -182,27 +183,22 @@ class BannerMessage extends StatelessWidget {
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: Icon(
messageType == BannerMessageType.error
? Icons.error_outline
: Icons.warning_amber_outlined,
size: actionsIconSize,
color:
messageType == BannerMessageType.error
? colorScheme.onErrorContainer
: colorScheme.onWarningContainer,
if (messageType != BannerMessageType.info)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: Icon(
messageType == BannerMessageType.error
? Icons.error_outline
: Icons.warning_amber_outlined,
size: actionsIconSize,
color: foregroundColor,
),
),
),
Expanded(
child: RichText(
text: TextSpan(
style: theme.regularTextStyle.copyWith(
color:
messageType == BannerMessageType.error
? colorScheme.onErrorContainer
: colorScheme.onWarningContainer,
color: foregroundColor,
),
children: textSpans,
),
Expand All @@ -213,10 +209,7 @@ class BannerMessage extends StatelessWidget {
icon: Icon(
Icons.close,
size: actionsIconSize,
color:
messageType == BannerMessageType.error
? colorScheme.onErrorContainer
: colorScheme.onWarningContainer,
color: foregroundColor,
),
onPressed:
() => bannerMessages.removeMessage(this, dismiss: true),
Expand All @@ -228,6 +221,26 @@ class BannerMessage extends StatelessWidget {
),
);
}

Color _backgroundColor(ColorScheme colorScheme) {
if (messageType == BannerMessageType.info) {
return colorScheme.secondaryContainer;
}

return (messageType == BannerMessageType.error
? colorScheme.errorContainer
: colorScheme.warningContainer);
}

Color _foregroundColor(ColorScheme colorScheme) {
if (messageType == BannerMessageType.info) {
return colorScheme.onSecondaryContainer;
}

return (messageType == BannerMessageType.error
? colorScheme.onErrorContainer
: colorScheme.onWarningContainer);
}
}

class _BannerError extends BannerMessage {
Expand All @@ -247,6 +260,14 @@ class BannerWarning extends BannerMessage {
}) : super(messageType: BannerMessageType.warning);
}

class BannerInfo extends BannerMessage {
const BannerInfo({
required super.key,
required super.textSpans,
required super.screenId,
}) : super(messageType: BannerMessageType.info);
}

class DebugModePerformanceMessage {
const DebugModePerformanceMessage(this.screenId);

Expand Down Expand Up @@ -503,6 +524,40 @@ The $codeType DevTools debugger is in maintenance mode. For the best debugging e
}
}

class WelcomeToNewInspectorMessage {
WelcomeToNewInspectorMessage(this.screenId)
: key = Key('WelcomeToNewInspectorMessage - $screenId');

final Key key;

final String screenId;

BannerMessage build(BuildContext context) {
const docsUrl = 'https://docs.flutter.dev/tools/devtools/inspector#new';
return BannerInfo(
key: key,
textSpans: [
const TextSpan(
text: '''
👋 Welcome to the new Flutter inspector! To get started, check out the ''',
),
GaLinkTextSpan(
link: GaLink(
display: 'documentation',
url: docsUrl,
gaScreenName: screenId,
gaSelectedItemDescription: gac.inspectorV2Docs,
),
context: context,
style: Theme.of(context).linkTextStyle,
),
const TextSpan(text: '.'),
],
screenId: screenId,
);
}
}

void maybePushDebugModePerformanceMessage(
BuildContext context,
String screenId,
Expand Down Expand Up @@ -541,6 +596,12 @@ void pushDebuggerIdeRecommendationMessage(
);
}

void pushWelcomeToNewInspectorMessage(BuildContext context, String screenId) {
bannerMessages.addMessage(
WelcomeToNewInspectorMessage(screenId).build(context),
);
}

extension BannerMessageThemeExtension on ThemeData {
TextStyle get warningMessageLinkStyle => regularTextStyle.copyWith(
decoration: TextDecoration.underline,
Expand Down
Loading
Loading