Enable WASM experiment for Flutter beta branches (#9455)
diff --git a/packages/devtools_app/lib/src/shared/feature_flags.dart b/packages/devtools_app/lib/src/shared/feature_flags.dart index d885a3e..b9a331c 100644 --- a/packages/devtools_app/lib/src/shared/feature_flags.dart +++ b/packages/devtools_app/lib/src/shared/feature_flags.dart
@@ -110,6 +110,16 @@ enabled: true, ); + /// Flag to enable refactors in the Flutter Property Editor sidebar. + /// + /// https://github.com/flutter/devtools/issues/9214 + static const wasmByDefault = FlutterChannelFeatureFlag( + name: 'wasmByDefault', + flutterChannel: FlutterChannel.beta, + enabledForDartApps: false, + enabledForFlutterAppsFallback: false, + ); + /// A set of all the boolean feature flags for debugging purposes. /// /// When adding a new boolean flag, you are responsible for adding it to this @@ -130,7 +140,7 @@ /// When adding a new Flutter channel flag, you are responsible for adding it /// to this map as well. static final _flutterChannelFlags = <FlutterChannelFeatureFlag>{ - // TODO(https://github.com/flutter/devtools/issues/9438): Add wasm flag. + wasmByDefault, }; /// A helper to print the status of all the feature flags.
diff --git a/packages/devtools_app/lib/src/shared/managers/banner_messages.dart b/packages/devtools_app/lib/src/shared/managers/banner_messages.dart index c3fc64a..45e0b77 100644 --- a/packages/devtools_app/lib/src/shared/managers/banner_messages.dart +++ b/packages/devtools_app/lib/src/shared/managers/banner_messages.dart
@@ -545,6 +545,39 @@ ); } +class WasmWelcomeMessage extends BannerInfo { + WasmWelcomeMessage() + : super( + key: const Key('WasmWelcomeMessage'), + screenId: universalScreenId, + dismissOnConnectionChanges: true, + buildTextSpans: (context) => [ + const TextSpan( + text: + '🚀 A faster and more performant DevTools is now available on WebAssembly! Click ', + ), + const TextSpan( + text: 'Enable', + style: TextStyle(fontWeight: FontWeight.bold), + ), + const TextSpan(text: ' to try it out now.'), + const TextSpan( + text: ' Please note that this will trigger a reload of DevTools.', + style: TextStyle(fontStyle: FontStyle.italic), + ), + ], + buildActions: (context) => [ + DevToolsButton( + label: 'Enable', + onPressed: () async { + await preferences.enableWasmInStorage(); + webReload(); + }, + ), + ], + ); +} + void maybePushDebugModePerformanceMessage(String screenId) { if (offlineDataController.showingOfflineData.value) return; if (serviceConnection.serviceManager.connectedApp?.isDebugFlutterAppNow ?? @@ -577,6 +610,10 @@ bannerMessages.addMessage(WelcomeToNewInspectorMessage(screenId: screenId)); } +void pushWasmWelcomeMessage() { + bannerMessages.addMessage(WasmWelcomeMessage()); +} + extension BannerMessageThemeExtension on ThemeData { TextStyle get warningMessageLinkStyle => regularTextStyle.copyWith( decoration: TextDecoration.underline,
diff --git a/packages/devtools_app/lib/src/shared/preferences/preferences.dart b/packages/devtools_app/lib/src/shared/preferences/preferences.dart index c54e260..32422f1 100644 --- a/packages/devtools_app/lib/src/shared/preferences/preferences.dart +++ b/packages/devtools_app/lib/src/shared/preferences/preferences.dart
@@ -19,6 +19,7 @@ import '../diagnostics/inspector_service.dart'; import '../feature_flags.dart'; import '../globals.dart'; +import '../managers/banner_messages.dart'; import '../primitives/query_parameters.dart'; import '../server/server.dart'; import '../utils/utils.dart'; @@ -65,6 +66,8 @@ /// A controller for global application preferences. class PreferencesController extends DisposableController with AutoDisposeControllerMixin { + static const _welcomeShownStorageId = 'wasmWelcomeShown'; + /// Whether the user preference for DevTools theme is set to dark mode. /// /// To check whether DevTools is using a light or dark theme, other parts of @@ -134,6 +137,13 @@ setGlobal(PreferencesController, this); } + /// Enables the wasm experiment in storage. + /// + /// This is used to persist the preference across reloads. + Future<void> enableWasmInStorage() async { + await storage.setValue(_ExperimentPreferences.wasm.storageKey, 'true'); + } + Future<void> _initDarkMode() async { final darkModeValue = await storage.getValue( _UiPreferences.darkMode.storageKey, @@ -181,6 +191,18 @@ ); } + // Maybe show the WASM welcome message on app connection if this is the + // first time the user is loading DevTools after the WASM experiment was + // enabled. + addAutoDisposeListener( + serviceConnection.serviceManager.connectedState, + () async { + if (serviceConnection.serviceManager.connectedState.value.connected) { + await _maybeShowWasmWelcomeMessage(); + } + }, + ); + addAutoDisposeListener(wasmEnabled, () async { final enabled = wasmEnabled.value; _log.fine('preference update (wasmEnabled = $enabled)'); @@ -247,6 +269,23 @@ toggleWasmEnabled(shouldEnableWasm); } + Future<void> _maybeShowWasmWelcomeMessage() async { + // If we have already shown the welcome message, don't show it again. + final welcomeAlreadyShown = await storage.getValue(_welcomeShownStorageId); + if (welcomeAlreadyShown == 'true') return; + + // Show the welcome message if the WASM experiment is enabled but the user + // is not using the WASM build. + final connectedApp = serviceConnection.serviceManager.connectedApp; + if (connectedApp != null && + FeatureFlags.wasmByDefault.isEnabled(connectedApp) && + !kIsWasm) { + // Mark the welcome message as shown. + await storage.setValue(_welcomeShownStorageId, 'true'); + pushWasmWelcomeMessage(); + } + } + Future<void> _initVerboseLogging() async { final verboseLoggingEnabledValue = await boolValueFromStorage( _GeneralPreferences.verboseLogging.name,
diff --git a/packages/devtools_app_shared/lib/src/utils/url/_url_stub.dart b/packages/devtools_app_shared/lib/src/utils/url/_url_stub.dart index 8f9649e..0990d64 100644 --- a/packages/devtools_app_shared/lib/src/utils/url/_url_stub.dart +++ b/packages/devtools_app_shared/lib/src/utils/url/_url_stub.dart
@@ -17,6 +17,11 @@ // Unused parameter lint doesn't make sense for stub files. void webRedirect(String url) {} +/// Performs a web reload using window.location.reload(). +/// +/// No-op for non-web platforms. +void webReload() {} + /// Updates the query parameter with [key] to the new [value], and optionally /// reloads the page when [reload] is true. ///
diff --git a/packages/devtools_app_shared/lib/src/utils/url/_url_web.dart b/packages/devtools_app_shared/lib/src/utils/url/_url_web.dart index 7ca399d..67e84ee 100644 --- a/packages/devtools_app_shared/lib/src/utils/url/_url_web.dart +++ b/packages/devtools_app_shared/lib/src/utils/url/_url_web.dart
@@ -16,6 +16,10 @@ window.location.replace(url); } +void webReload() { + window.location.reload(); +} + void updateQueryParameter(String key, String? value, {bool reload = false}) { final newQueryParams = Map.of(loadQueryParams()); if (value == null) {