@@ -13,12 +13,15 @@ import '../../../shared/analytics/constants.dart' as gac;
1313import '../../../shared/globals.dart' ;
1414import '../../../shared/primitives/utils.dart' ;
1515import '../../../shared/server/server.dart' as server;
16+ import '../../../shared/ui/common_widgets.dart' ;
1617import '../deep_links_controller.dart' ;
1718import '../deep_links_model.dart' ;
1819import 'root_selector.dart' ;
1920
2021const _kLinearProgressIndicatorWidth = 280.0 ;
2122
23+ enum DeepLinksTarget { android, ios }
24+
2225/// A view for selecting a Flutter project.
2326class SelectProjectView extends StatefulWidget {
2427 const SelectProjectView ({super .key});
@@ -131,7 +134,7 @@ class _SelectProjectViewState extends State<SelectProjectView> {
131134 gac.deeplink,
132135 gac.AnalyzeFlutterProject .flutterInvalidProjectSelected.name,
133136 );
134- await showNonFlutterProjectDialog ( );
137+ await _showFlutterProjectMissingBuildOptionsDialog (directory );
135138 return ;
136139 }
137140 controller.selectedProject.value = FlutterProject (
@@ -144,6 +147,119 @@ class _SelectProjectViewState extends State<SelectProjectView> {
144147 });
145148 }
146149
150+ Future <void > _showFlutterProjectMissingBuildOptionsDialog (
151+ String appPath,
152+ ) async {
153+ await showDialog (
154+ context: context,
155+ builder: (_) {
156+ final theme = Theme .of (context);
157+ return DevToolsDialog (
158+ title: const Text ('No iOS or Android build options found.' ),
159+ content: SizedBox (
160+ width: defaultDialogWidth,
161+ child: Column (
162+ crossAxisAlignment: CrossAxisAlignment .start,
163+ children: [
164+ const Text (
165+ 'DevTools could not verify the build options for this project.' ,
166+ ),
167+ const SizedBox (height: largeSpacing),
168+ ..._deepLinksInstructions (
169+ theme: theme,
170+ appPath: appPath,
171+ target: DeepLinksTarget .android,
172+ ),
173+ const SizedBox (height: largeSpacing),
174+ ..._deepLinksInstructions (
175+ theme: theme,
176+ appPath: appPath,
177+ target: DeepLinksTarget .ios,
178+ ),
179+ ],
180+ ),
181+ ),
182+ actions: const [DialogCloseButton ()],
183+ );
184+ },
185+ );
186+ setState (() {
187+ _retrievingFlutterProject = false ;
188+ });
189+ }
190+
191+ List <Widget > _deepLinksInstructions ({
192+ required ThemeData theme,
193+ required String appPath,
194+ required DeepLinksTarget target,
195+ }) {
196+ final commandStyle = theme.subtleTextStyle.copyWith (
197+ fontFamily: 'RobotoMono' ,
198+ );
199+ const commandPadding = EdgeInsets .symmetric (
200+ horizontal: denseSpacing,
201+ vertical: densePadding,
202+ );
203+ final title = switch (target) {
204+ DeepLinksTarget .android => 'Android' ,
205+ DeepLinksTarget .ios => 'iOS' ,
206+ };
207+ final directory = switch (target) {
208+ DeepLinksTarget .android => '/android' ,
209+ DeepLinksTarget .ios => '/ios' ,
210+ };
211+ final documentationUrl = switch (target) {
212+ DeepLinksTarget .android => 'https://docs.flutter.dev/deployment/android' ,
213+ DeepLinksTarget .ios => 'https://docs.flutter.dev/deployment/ios' ,
214+ };
215+ final command = switch (target) {
216+ DeepLinksTarget .android =>
217+ 'flutter analyze --android --list-build-variants' ,
218+ DeepLinksTarget .ios => 'flutter analyze --ios --list-build-options' ,
219+ };
220+
221+ return [
222+ Text ('For $title ' , style: theme.textTheme.titleMedium),
223+ const SizedBox (height: intermediateSpacing),
224+ RichText (
225+ text: TextSpan (
226+ style: theme.regularTextStyle,
227+ children: [
228+ TextSpan (
229+ text:
230+ 'These are configured in the $directory directory. Please refer to the ' ,
231+ ),
232+ GaLinkTextSpan (
233+ link: GaLink (
234+ display: 'Flutter documentation' ,
235+ url: documentationUrl,
236+ ),
237+ context: context,
238+ ),
239+ const TextSpan (text: ' for more information.' ),
240+ ],
241+ ),
242+ ),
243+ const SizedBox (height: intermediateSpacing),
244+ const Text (
245+ 'To confirm your setup, run the following command in your terminal:' ,
246+ ),
247+ const SizedBox (height: denseSpacing),
248+ Card (
249+ child: Padding (
250+ padding: commandPadding,
251+ child: Row (
252+ mainAxisAlignment: MainAxisAlignment .spaceBetween,
253+ children: [
254+ Flexible (child: Text ('$command $appPath ' , style: commandStyle)),
255+ CopyToClipboardControl (dataProvider: () => '$command $appPath ' ),
256+ ],
257+ ),
258+ ),
259+ ),
260+ ];
261+ }
262+
147263 @override
148264 Widget build (BuildContext context) {
149265 final theme = Theme .of (context);
@@ -156,7 +272,7 @@ class _SelectProjectViewState extends State<SelectProjectView> {
156272 Padding (
157273 padding: const EdgeInsets .all (extraLargeSpacing),
158274 child: Text (
159- 'Select a local flutter project to check the status of all deep links.' ,
275+ 'Select a local Flutter project to check the status of all deep links.' ,
160276 textAlign: TextAlign .center,
161277 style: Theme .of (context).textTheme.titleMedium,
162278 ),
0 commit comments