From ec2f43b232f00984c2f8c8d9e4cb4402ff257234 Mon Sep 17 00:00:00 2001 From: Abdelrahman Saed Date: Wed, 29 Jul 2026 01:38:53 +0300 Subject: [PATCH 1/5] Add tutorialVideoUrl field to ScreenMetaData for deep links video --- .../devtools_app/lib/src/shared/framework/screen.dart | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/devtools_app/lib/src/shared/framework/screen.dart b/packages/devtools_app/lib/src/shared/framework/screen.dart index 6e090ff7bc0..65ff975bdee 100644 --- a/packages/devtools_app/lib/src/shared/framework/screen.dart +++ b/packages/devtools_app/lib/src/shared/framework/screen.dart @@ -124,6 +124,7 @@ enum ScreenMetaData { requiresConnection: false, requiresDartVm: true, requiresFlutter: true, + tutorialVideoUrl: 'https://www.youtube.com/watch?v=d7sZL6h1Elw', ), vmTools( 'vm-tools', @@ -154,6 +155,7 @@ enum ScreenMetaData { this.worksWithOfflineData = false, this.requiresLibrary, this.tutorialVideoTimestamp, + this.tutorialVideoUrl, }) : assert( icon == null || iconAsset == null, 'Only one of icon or iconAsset may be specified.', @@ -179,6 +181,13 @@ enum ScreenMetaData { /// a particular chapter. final String? tutorialVideoTimestamp; + /// A custom video tutorial URL for a screen. + /// + /// If provided, this URL will be used instead of the default + /// "Dive in to DevTools" YouTube video timestamp. This is used for + /// screens that have their own dedicated video tutorials. + final String? tutorialVideoUrl; + /// Looks up the [ScreenMetaData] value for the screen [id]. static ScreenMetaData? lookup(String id) { return ScreenMetaData.values.firstWhereOrNull((screen) => screen.id == id); From e316f3c85b7d297d7656e9265a7f3988d487d6b7 Mon Sep 17 00:00:00 2001 From: Abdelrahman Saed Date: Wed, 29 Jul 2026 01:39:03 +0300 Subject: [PATCH 2/5] Update VideoTutorialLink to support custom video URLs Use the tutorialVideoUrl from ScreenMetaData when available, falling back to the default DevTools YouTube video timestamp. --- .../lib/src/framework/scaffold/status_line.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/devtools_app/lib/src/framework/scaffold/status_line.dart b/packages/devtools_app/lib/src/framework/scaffold/status_line.dart index 54e78dc2954..78843444db6 100644 --- a/packages/devtools_app/lib/src/framework/scaffold/status_line.dart +++ b/packages/devtools_app/lib/src/framework/scaffold/status_line.dart @@ -90,7 +90,9 @@ class StatusLine extends StatelessWidget { final pageStatus = currentScreen.buildStatus(context); final widerThanXxs = screenWidth > MediaSize.xxs; final screenMetaData = ScreenMetaData.lookup(currentScreen.screenId); - final showVideoTutorial = screenMetaData?.tutorialVideoTimestamp != null; + final showVideoTutorial = + screenMetaData?.tutorialVideoTimestamp != null || + screenMetaData?.tutorialVideoUrl != null; return [ Row( mainAxisSize: MainAxisSize.min, @@ -261,7 +263,7 @@ class VideoTutorialLink extends StatelessWidget { icon: Icons.ondemand_video_rounded, link: GaLink( display: screenWidth <= MediaSize.xs ? 'Tutorial' : 'Watch tutorial', - url: + url: screenMetaData.tutorialVideoUrl ?? '$_devToolsYouTubeVideoUrl${screenMetaData.tutorialVideoTimestamp}', gaScreenName: screenMetaData.id, gaSelectedItemDescription: From b5acea34d24511ba8d512579fe7c7e0304ec26de Mon Sep 17 00:00:00 2001 From: Abdelrahman Saed Date: Wed, 29 Jul 2026 02:53:16 +0300 Subject: [PATCH 3/5] Use youtu.be short URL format for deep links tutorial video --- packages/devtools_app/lib/src/shared/framework/screen.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/devtools_app/lib/src/shared/framework/screen.dart b/packages/devtools_app/lib/src/shared/framework/screen.dart index 65ff975bdee..ac030266df5 100644 --- a/packages/devtools_app/lib/src/shared/framework/screen.dart +++ b/packages/devtools_app/lib/src/shared/framework/screen.dart @@ -124,7 +124,7 @@ enum ScreenMetaData { requiresConnection: false, requiresDartVm: true, requiresFlutter: true, - tutorialVideoUrl: 'https://www.youtube.com/watch?v=d7sZL6h1Elw', + tutorialVideoUrl: 'https://youtu.be/d7sZL6h1Elw', ), vmTools( 'vm-tools', From d3213d59b6b4a73bbceb9fd0dfcbb2d044ec6ff1 Mon Sep 17 00:00:00 2001 From: Abdelrahman Saed Date: Wed, 29 Jul 2026 02:55:54 +0300 Subject: [PATCH 4/5] Move deep links tutorial video URL to a named constant --- packages/devtools_app/lib/src/shared/framework/screen.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/devtools_app/lib/src/shared/framework/screen.dart b/packages/devtools_app/lib/src/shared/framework/screen.dart index ac030266df5..32f3d21e4bb 100644 --- a/packages/devtools_app/lib/src/shared/framework/screen.dart +++ b/packages/devtools_app/lib/src/shared/framework/screen.dart @@ -27,6 +27,8 @@ const _kNetworkDisconnectExperience = bool.fromEnvironment( defaultValue: true, ); +const _deepLinksTutorialVideoUrl = 'https://youtu.be/d7sZL6h1Elw'; + enum ScreenMetaData { home( 'home', @@ -124,7 +126,7 @@ enum ScreenMetaData { requiresConnection: false, requiresDartVm: true, requiresFlutter: true, - tutorialVideoUrl: 'https://youtu.be/d7sZL6h1Elw', + tutorialVideoUrl: _deepLinksTutorialVideoUrl, ), vmTools( 'vm-tools', From 830ab88f13b92da336fb4005f2f301a6ba18a4cb Mon Sep 17 00:00:00 2001 From: Abdelrahman Saed Date: Wed, 29 Jul 2026 02:59:46 +0300 Subject: [PATCH 5/5] Assert that VideoTutorialLink has a video URL or timestamp --- .../lib/src/framework/scaffold/status_line.dart | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/devtools_app/lib/src/framework/scaffold/status_line.dart b/packages/devtools_app/lib/src/framework/scaffold/status_line.dart index 78843444db6..9c362dad48e 100644 --- a/packages/devtools_app/lib/src/framework/scaffold/status_line.dart +++ b/packages/devtools_app/lib/src/framework/scaffold/status_line.dart @@ -239,12 +239,15 @@ class DocumentationLink extends StatelessWidget { /// A widget that links to the "Dive in to DevTools" YouTube video at the /// chapter for the given [screenMetaData]. class VideoTutorialLink extends StatelessWidget { - const VideoTutorialLink({ + VideoTutorialLink({ super.key, required this.screenMetaData, required this.screenWidth, required this.highlightForConnection, - }); + }) : assert( + screenMetaData.tutorialVideoTimestamp != null || + screenMetaData.tutorialVideoUrl != null, + ); final ScreenMetaData screenMetaData; @@ -263,7 +266,8 @@ class VideoTutorialLink extends StatelessWidget { icon: Icons.ondemand_video_rounded, link: GaLink( display: screenWidth <= MediaSize.xs ? 'Tutorial' : 'Watch tutorial', - url: screenMetaData.tutorialVideoUrl ?? + url: + screenMetaData.tutorialVideoUrl ?? '$_devToolsYouTubeVideoUrl${screenMetaData.tutorialVideoTimestamp}', gaScreenName: screenMetaData.id, gaSelectedItemDescription: