Skip to content

Commit 1534b5b

Browse files
kenzieschmollCoderDake
authored andcommitted
Add Use Legacy Trace Viewer setting to the Performance page (flutter#4579)
1 parent e129c00 commit 1534b5b

File tree

6 files changed

+89
-40
lines changed

6 files changed

+89
-40
lines changed

packages/devtools_app/lib/src/screens/performance/panes/controls/performance_settings.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import 'package:flutter/material.dart';
66

7+
import '../../../../primitives/feature_flags.dart';
78
import '../../../../shared/common_widgets.dart';
89
import '../../../../shared/dialogs.dart';
910
import '../../../../shared/globals.dart';
@@ -137,6 +138,12 @@ class FlutterSettings extends StatelessWidget {
137138
notifier: controller.badgeTabForJankyFrames as ValueNotifier<bool?>,
138139
title: 'Badge Performance tab when Flutter UI jank is detected',
139140
),
141+
if (FeatureFlags.embeddedPerfetto)
142+
CheckboxSetting(
143+
notifier: controller.useLegacyTraceViewer,
144+
title: 'Use legacy trace viewer',
145+
onChanged: controller.toggleUseLegacyTraceViewer,
146+
),
140147
],
141148
);
142149
}

packages/devtools_app/lib/src/screens/performance/panes/timeline_events/perfetto/_perfetto_controller_web.dart

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,11 +133,28 @@ class PerfettoController extends DisposableController
133133
);
134134
}
135135

136-
void _postMessage(dynamic message) {
137-
_perfettoIFrame.contentWindow!.postMessage(
138-
message,
139-
_perfettoUrl,
140-
);
136+
void _postMessage(dynamic message) async {
137+
final callback = () {
138+
_perfettoIFrame.contentWindow!.postMessage(
139+
message,
140+
_perfettoUrl,
141+
);
142+
};
143+
if (_perfettoIFrame.contentWindow != null) {
144+
callback.call();
145+
} else {
146+
late StreamSubscription? onLoad;
147+
onLoad = _perfettoIFrame.onLoad.listen((event) {
148+
assert(
149+
_perfettoIFrame.contentWindow != null,
150+
'Something went wrong. The iFrame\'s contentWindow is null after the'
151+
' onLoad event.',
152+
);
153+
callback.call();
154+
onLoad?.cancel();
155+
onLoad = null;
156+
});
157+
}
141158
}
142159

143160
void _postMessageWithId(String id, {Map<String, dynamic> args = const {}}) {

packages/devtools_app/lib/src/screens/performance/performance_controller.dart

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ class PerformanceController extends DisposableController
7272

7373
final perfettoController = createPerfettoController();
7474

75+
final useLegacyTraceViewer =
76+
ValueNotifier<bool>(!FeatureFlags.embeddedPerfetto || !kIsWeb);
77+
7578
final _exportController = ExportController();
7679

7780
/// The currently selected timeline event.
@@ -699,7 +702,7 @@ class PerformanceController extends DisposableController
699702
}
700703

701704
FutureOr<void> processTraceEvents(List<TraceEventWrapper> traceEvents) async {
702-
if (FeatureFlags.embeddedPerfetto) {
705+
if (FeatureFlags.embeddedPerfetto && !useLegacyTraceViewer.value) {
703706
await perfettoController.loadTrace(traceEvents);
704707
} else {
705708
await _processTraceEvents(traceEvents);
@@ -929,6 +932,11 @@ class PerformanceController extends DisposableController
929932
_httpTimelineLoggingEnabled.value = state;
930933
}
931934

935+
void toggleUseLegacyTraceViewer(bool? value) {
936+
useLegacyTraceViewer.value = value ?? false;
937+
processAvailableEvents();
938+
}
939+
932940
/// Clears the timeline data currently stored by the controller as well the
933941
/// VM timeline if a connected app is present.
934942
Future<void> clearData() async {

packages/devtools_app/lib/src/screens/performance/performance_screen.dart

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -164,21 +164,26 @@ class PerformanceScreenBodyState extends State<PerformanceScreenBody>
164164
},
165165
),
166166
Expanded(
167-
child: FeatureFlags.embeddedPerfetto
168-
? tabbedPerformanceView
169-
: Split(
170-
axis: Axis.vertical,
171-
initialFractions: const [0.7, 0.3],
172-
children: [
173-
tabbedPerformanceView,
174-
ValueListenableBuilder<TimelineEvent?>(
175-
valueListenable: controller.selectedTimelineEvent,
176-
builder: (context, selectedEvent, _) {
177-
return EventDetails(selectedEvent);
178-
},
179-
),
180-
],
181-
),
167+
child: ValueListenableBuilder<bool>(
168+
valueListenable: controller.useLegacyTraceViewer,
169+
builder: (context, useLegacy, _) {
170+
return FeatureFlags.embeddedPerfetto && !useLegacy
171+
? tabbedPerformanceView
172+
: Split(
173+
axis: Axis.vertical,
174+
initialFractions: const [0.7, 0.3],
175+
children: [
176+
tabbedPerformanceView,
177+
ValueListenableBuilder<TimelineEvent?>(
178+
valueListenable: controller.selectedTimelineEvent,
179+
builder: (context, selectedEvent, _) {
180+
return EventDetails(selectedEvent);
181+
},
182+
),
183+
],
184+
);
185+
},
186+
),
182187
),
183188
],
184189
);

packages/devtools_app/lib/src/screens/performance/tabbed_performance_view.dart

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -84,19 +84,25 @@ class _TabbedPerformanceViewState extends State<TabbedPerformanceView>
8484

8585
final isFlutterApp = serviceManager.connectedApp!.isFlutterAppNow!;
8686
final tabViews = [
87-
FeatureFlags.embeddedPerfetto
88-
? KeepAliveWrapper(
89-
child: EmbeddedPerfetto(
90-
perfettoController: controller.perfettoController,
91-
),
92-
)
93-
: KeepAliveWrapper(
87+
ValueListenableBuilder<bool>(
88+
valueListenable: controller.useLegacyTraceViewer,
89+
builder: (context, useLegacy, _) {
90+
if (useLegacy || !FeatureFlags.embeddedPerfetto) {
91+
return KeepAliveWrapper(
9492
child: TimelineEventsView(
9593
controller: controller,
9694
processing: widget.processing,
9795
processingProgress: widget.processingProgress,
9896
),
97+
);
98+
}
99+
return KeepAliveWrapper(
100+
child: EmbeddedPerfetto(
101+
perfettoController: controller.perfettoController,
99102
),
103+
);
104+
},
105+
),
100106
if (frameAnalysisSupported && isFlutterApp)
101107
KeepAliveWrapper(
102108
child: frameAnalysisView,
@@ -121,18 +127,23 @@ class _TabbedPerformanceViewState extends State<TabbedPerformanceView>
121127
return [
122128
_buildTab(
123129
tabName: 'Timeline Events',
124-
trailing: Row(
125-
mainAxisAlignment: MainAxisAlignment.end,
126-
children: [
127-
if (!FeatureFlags.embeddedPerfetto) ...[
128-
_buildSearchField(searchFieldEnabled),
129-
const FlameChartHelpButton(
130-
gaScreen: PerformanceScreen.id,
131-
gaSelection: analytics_constants.timelineFlameChartHelp,
132-
),
133-
],
134-
RefreshTimelineEventsButton(controller: controller),
135-
],
130+
trailing: ValueListenableBuilder<bool>(
131+
valueListenable: controller.useLegacyTraceViewer,
132+
builder: (context, useLegacy, _) {
133+
return Row(
134+
mainAxisAlignment: MainAxisAlignment.end,
135+
children: [
136+
if (useLegacy || !FeatureFlags.embeddedPerfetto) ...[
137+
_buildSearchField(searchFieldEnabled),
138+
const FlameChartHelpButton(
139+
gaScreen: PerformanceScreen.id,
140+
gaSelection: analytics_constants.timelineFlameChartHelp,
141+
),
142+
],
143+
RefreshTimelineEventsButton(controller: controller),
144+
],
145+
);
146+
},
136147
),
137148
),
138149
if (frameAnalysisSupported && isFlutterApp)

packages/devtools_test/lib/src/mocks/generated_mocks_factories.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ MockPerformanceController createMockPerformanceControllerWithDefaults() {
2323
when(controller.selectedFrame)
2424
.thenReturn(const FixedValueListenable<FlutterFrame?>(null));
2525
when(controller.displayRefreshRate).thenReturn(ValueNotifier<double>(60.0));
26+
when(controller.useLegacyTraceViewer).thenReturn(ValueNotifier<bool>(true));
2627
return controller;
2728
}
2829

0 commit comments

Comments
 (0)