Add documentation links to app size screen and handle null files (#9689)
diff --git a/packages/devtools_app/lib/devtools.dart b/packages/devtools_app/lib/devtools.dart
index 199647b..44658c3 100644
--- a/packages/devtools_app/lib/devtools.dart
+++ b/packages/devtools_app/lib/devtools.dart
@@ -10,4 +10,4 @@
/// Note: a regexp in the `dt update-version' command logic matches the constant
/// declaration `const version =`. If you change the declaration you must also
/// modify the regex in the `dt update-version' command logic.
-const version = '2.56.0';
+const version = '2.57.0-dev.0';
diff --git a/packages/devtools_app/lib/src/screens/app_size/app_size_screen.dart b/packages/devtools_app/lib/src/screens/app_size/app_size_screen.dart
index 36e3406..ff9deef 100644
--- a/packages/devtools_app/lib/src/screens/app_size/app_size_screen.dart
+++ b/packages/devtools_app/lib/src/screens/app_size/app_size_screen.dart
@@ -116,7 +116,14 @@
testAppSizeFile = await server.requestTestAppSizeFile(testFilePath);
}
- // TODO(kenz): add error handling if the files are null
+ final errorMessages = <String>[
+ if (baseAppSizeFile == null) 'base app size file: $baseFilePath',
+ if (testAppSizeFile == null) 'test app size file: $testFilePath',
+ ];
+ if (errorMessages.isNotEmpty) {
+ _pushErrorMessage('Failed to load ${errorMessages.join(' and ')}.');
+ }
+
if (baseAppSizeFile != null) {
if (testAppSizeFile != null) {
controller.loadDiffTreeFromJsonFiles(
@@ -306,15 +313,78 @@
}
}
+enum ImportInstructionType { analysis, diffOld, diffNew }
+
+class _ImportInstructions extends StatelessWidget {
+ const _ImportInstructions({this.type = ImportInstructionType.analysis});
+
+ final ImportInstructionType type;
+
+ @override
+ Widget build(BuildContext context) {
+ final theme = Theme.of(context);
+
+ List<InlineSpan> buildInstructionText() {
+ final article = type == ImportInstructionType.diffNew ? 'a' : 'an';
+ final boldText = type == ImportInstructionType.diffOld
+ ? 'original (old)'
+ : type == ImportInstructionType.diffNew
+ ? 'modified (new)'
+ : null;
+
+ return [
+ TextSpan(
+ text: 'Drag and drop $article ',
+ style: theme.regularTextStyle,
+ ),
+ if (boldText != null)
+ TextSpan(text: boldText, style: theme.boldTextStyle),
+ TextSpan(
+ text:
+ '${boldText != null ? ' ' : ''}AOT snapshot or size analysis file'
+ ' for debugging, or click "Open file".',
+ style: theme.regularTextStyle,
+ ),
+ ];
+ }
+
+ return Column(
+ mainAxisSize: MainAxisSize.min,
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ RichText(
+ textAlign: TextAlign.center,
+ text: TextSpan(children: buildInstructionText()),
+ ),
+ const SizedBox(height: densePadding),
+ RichText(
+ textAlign: TextAlign.center,
+ text: TextSpan(
+ children: [
+ TextSpan(text: 'Read ', style: theme.regularTextStyle),
+ LinkTextSpan(
+ link: const Link(
+ display: 'documentation',
+ url:
+ 'https://docs.flutter.dev/tools/devtools/app-size#generating-size-files',
+ ),
+ context: context,
+ ),
+ TextSpan(
+ text: ' to learn how to generate these files.',
+ style: theme.regularTextStyle,
+ ),
+ ],
+ ),
+ ),
+ ],
+ );
+ }
+}
+
class AnalysisView extends StatefulWidget {
const AnalysisView({super.key});
- // TODO(kenz): add links to documentation on how to generate these files, and
- // mention the import file button once it is hooked up to a file picker.
- static const importInstructions =
- 'Drag and drop an AOT snapshot or'
- ' size analysis file for debugging';
-
@override
State<AnalysisView> createState() => _AnalysisViewState();
}
@@ -382,7 +452,7 @@
children: [
Flexible(
child: FileImportContainer(
- instructions: AnalysisView.importInstructions,
+ instructionsWidget: const _ImportInstructions(),
actionText: 'Analyze Size',
gaScreen: gac.appSize,
gaSelectionImport: gac.importFileSingle,
@@ -407,15 +477,6 @@
class DiffView extends StatefulWidget {
const DiffView({super.key});
- // TODO(kenz): add links to documentation on how to generate these files, and
- // mention the import file button once it is hooked up to a file picker.
- static const importOldInstructions =
- 'Drag and drop an original (old) AOT '
- 'snapshot or size analysis file for debugging';
- static const importNewInstructions =
- 'Drag and drop a modified (new) AOT '
- 'snapshot or size analysis file for debugging';
-
@override
State<DiffView> createState() => _DiffViewState();
}
@@ -490,9 +551,12 @@
child: DualFileImportContainer(
firstFileTitle: 'Old',
secondFileTitle: 'New',
- // TODO(kenz): perhaps bold "original" and "modified".
- firstInstructions: DiffView.importOldInstructions,
- secondInstructions: DiffView.importNewInstructions,
+ firstInstructionsWidget: const _ImportInstructions(
+ type: ImportInstructionType.diffOld,
+ ),
+ secondInstructionsWidget: const _ImportInstructions(
+ type: ImportInstructionType.diffNew,
+ ),
actionText: 'Analyze Diff',
gaScreen: gac.appSize,
gaSelectionImportFirst: gac.importFileDiffFirst,
diff --git a/packages/devtools_app/lib/src/shared/ui/file_import.dart b/packages/devtools_app/lib/src/shared/ui/file_import.dart
index 3ba61c4..3a425f6 100644
--- a/packages/devtools_app/lib/src/shared/ui/file_import.dart
+++ b/packages/devtools_app/lib/src/shared/ui/file_import.dart
@@ -218,9 +218,10 @@
class FileImportContainer extends StatefulWidget {
const FileImportContainer({
- required this.instructions,
required this.gaScreen,
required this.gaSelectionImport,
+ this.instructions,
+ this.instructionsWidget,
this.title,
this.backgroundColor,
this.gaSelectionAction,
@@ -230,13 +231,15 @@
this.onFileCleared,
this.extensions = const ['json'],
super.key,
- });
+ }) : assert((instructions == null) != (instructionsWidget == null));
final String? title;
final Color? backgroundColor;
- final String instructions;
+ final String? instructions;
+
+ final Widget? instructionsWidget;
/// The title of the action button.
final String? actionText;
@@ -276,7 +279,10 @@
Text(title, style: const TextStyle(fontSize: 18.0)),
const SizedBox(height: extraLargeSpacing),
],
- CenteredMessage(message: widget.instructions),
+ if (widget.instructionsWidget != null)
+ widget.instructionsWidget!
+ else if (widget.instructions != null)
+ CenteredMessage(message: widget.instructions),
const SizedBox(height: denseSpacing),
_buildImportFileRow(),
if (widget.actionText != null && widget.onAction != null)
@@ -477,8 +483,10 @@
super.key,
required this.firstFileTitle,
required this.secondFileTitle,
- required this.firstInstructions,
- required this.secondInstructions,
+ this.firstInstructions,
+ this.secondInstructions,
+ this.firstInstructionsWidget,
+ this.secondInstructionsWidget,
required this.actionText,
required this.onAction,
required this.gaScreen,
@@ -489,8 +497,10 @@
final String firstFileTitle;
final String secondFileTitle;
- final String firstInstructions;
- final String secondInstructions;
+ final String? firstInstructions;
+ final String? secondInstructions;
+ final Widget? firstInstructionsWidget;
+ final Widget? secondInstructionsWidget;
final String gaScreen;
final String gaSelectionImportFirst;
final String gaSelectionImportSecond;
@@ -525,6 +535,7 @@
title: widget.firstFileTitle,
backgroundColor: backgroundColor,
instructions: widget.firstInstructions,
+ instructionsWidget: widget.firstInstructionsWidget,
onFileSelected: onFirstFileSelected,
onFileCleared: onFirstFileCleared,
gaScreen: widget.gaScreen,
@@ -539,6 +550,7 @@
title: widget.secondFileTitle,
backgroundColor: backgroundColor,
instructions: widget.secondInstructions,
+ instructionsWidget: widget.secondInstructionsWidget,
onFileSelected: onSecondFileSelected,
onFileCleared: onSecondFileCleared,
gaScreen: widget.gaScreen,
diff --git a/packages/devtools_app/pubspec.yaml b/packages/devtools_app/pubspec.yaml
index 17dbf52..ce47ca0 100644
--- a/packages/devtools_app/pubspec.yaml
+++ b/packages/devtools_app/pubspec.yaml
@@ -7,7 +7,7 @@
# Note: this version should only be updated by running the 'dt update-version'
# command that updates the version here and in 'devtools.dart'.
-version: 2.56.0
+version: 2.57.0-dev.0
repository: https://github.com/flutter/devtools/tree/master/packages/devtools_app
diff --git a/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md b/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md
index b98ca75..9963ddc 100644
--- a/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md
+++ b/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md
@@ -6,9 +6,9 @@
This is a draft for future release notes that are going to land on
[the Flutter website](https://docs.flutter.dev/tools/devtools/release-notes).
-# DevTools 2.56.0 release notes
+# DevTools 2.57.0 release notes
-The 2.56.0 release of the Dart and Flutter DevTools
+The 2.57.0 release of the Dart and Flutter DevTools
includes the following changes among other general improvements.
To learn more about DevTools, check out the
[DevTools overview](/tools/devtools).
@@ -39,7 +39,8 @@
## Network profiler updates
-- Fix crash in the Network tab when viewing binary multipart request or response bodies (#9978)
+- Fix crash in the Network tab when viewing binary multipart request or
+response bodies. [#9680](https://github.com/flutter/devtools/pull/9680)
## Logging updates
@@ -47,7 +48,7 @@
## App size tool updates
-TODO: Remove this section if there are not any updates.
+- Added documentation links and improved handling for null files. [#9689](https://github.com/flutter/devtools/pull/9689)
## Deep links tool updates
@@ -68,4 +69,4 @@
## Full commit history
To find a complete list of changes in this release, check out the
-[DevTools git log](https://github.com/flutter/devtools/tree/v2.56.0).
+[DevTools git log](https://github.com/flutter/devtools/tree/v2.57.0).
diff --git a/packages/devtools_app/test/screens/app_size/app_size_screen_test.dart b/packages/devtools_app/test/screens/app_size/app_size_screen_test.dart
index 695439d..1351278 100644
--- a/packages/devtools_app/test/screens/app_size/app_size_screen_test.dart
+++ b/packages/devtools_app/test/screens/app_size/app_size_screen_test.dart
@@ -214,7 +214,9 @@
expect(find.byType(ClearButton), findsOneWidget);
expect(find.byType(FileImportContainer), findsOneWidget);
- expect(find.text(AnalysisView.importInstructions), findsOneWidget);
+ const importInstructions =
+ 'Drag and drop an AOT snapshot or size analysis file for debugging, or click "Open file".';
+ expect(find.richText(importInstructions), findsOneWidget);
expect(find.text('No File Selected'), findsOneWidget);
appSizeController.loadTreeFromJsonFile(
@@ -227,7 +229,7 @@
await tester.pumpAndSettle();
expect(find.byType(FileImportContainer), findsNothing);
- expect(find.text(AnalysisView.importInstructions), findsNothing);
+ expect(find.richText(importInstructions), findsNothing);
expect(find.text('No File Selected'), findsNothing);
expect(find.byType(AnalysisView), findsOneWidget);
expect(
@@ -261,7 +263,9 @@
await tester.pumpAndSettle();
expect(find.byType(FileImportContainer), findsOneWidget);
- expect(find.text(AnalysisView.importInstructions), findsOneWidget);
+ const importInstructions =
+ 'Drag and drop an AOT snapshot or size analysis file for debugging, or click "Open file".';
+ expect(find.richText(importInstructions), findsOneWidget);
expect(find.text('No File Selected'), findsOneWidget);
});
});
@@ -302,8 +306,12 @@
expect(find.byType(DualFileImportContainer), findsOneWidget);
expect(find.byType(FileImportContainer), findsNWidgets(2));
- expect(find.text(DiffView.importOldInstructions), findsOneWidget);
- expect(find.text(DiffView.importNewInstructions), findsOneWidget);
+ const importOldInstructions =
+ 'Drag and drop an original (old) AOT snapshot or size analysis file for debugging, or click "Open file".';
+ const importNewInstructions =
+ 'Drag and drop a modified (new) AOT snapshot or size analysis file for debugging, or click "Open file".';
+ expect(find.richText(importOldInstructions), findsOneWidget);
+ expect(find.richText(importNewInstructions), findsOneWidget);
expect(find.text('No File Selected'), findsNWidgets(2));
});
@@ -323,8 +331,12 @@
await tester.pumpAndSettle();
expect(find.byType(FileImportContainer), findsNothing);
- expect(find.text(DiffView.importOldInstructions), findsNothing);
- expect(find.text(DiffView.importNewInstructions), findsNothing);
+ const importOldInstructions =
+ 'Drag and drop an original (old) AOT snapshot or size analysis file for debugging, or click "Open file".';
+ const importNewInstructions =
+ 'Drag and drop a modified (new) AOT snapshot or size analysis file for debugging, or click "Open file".';
+ expect(find.richText(importOldInstructions), findsNothing);
+ expect(find.richText(importNewInstructions), findsNothing);
expect(find.text('No File Selected'), findsNothing);
expect(find.byType(DiffView), findsOneWidget);
@@ -393,8 +405,12 @@
expect(find.byType(DualFileImportContainer), findsOneWidget);
expect(find.byType(FileImportContainer), findsNWidgets(2));
- expect(find.text(DiffView.importOldInstructions), findsOneWidget);
- expect(find.text(DiffView.importNewInstructions), findsOneWidget);
+ const importOldInstructions =
+ 'Drag and drop an original (old) AOT snapshot or size analysis file for debugging, or click "Open file".';
+ const importNewInstructions =
+ 'Drag and drop a modified (new) AOT snapshot or size analysis file for debugging, or click "Open file".';
+ expect(find.richText(importOldInstructions), findsOneWidget);
+ expect(find.richText(importNewInstructions), findsOneWidget);
expect(find.text('No File Selected'), findsNWidgets(2));
});
});