From 15ad3afa2e0a13559d1ccaa36f5fd47d674024fe Mon Sep 17 00:00:00 2001 From: Sol Mendiola <57235692+SolMendiola@users.noreply.github.com> Date: Wed, 25 Jan 2023 11:25:32 -0300 Subject: [PATCH] feat: Added new screen of videos (#74) * Added new screen of videos * Resolve comments --- android/app/src/main/AndroidManifest.xml | 6 ++++ assets/images/1.5x/ic_youtube_logo.png | Bin 0 -> 567 bytes assets/images/2.0x/ic_youtube_logo.png | Bin 0 -> 701 bytes assets/images/3.0x/ic_youtube_logo.png | Bin 0 -> 930 bytes assets/images/4.0x/ic_youtube_logo.png | Bin 0 -> 1242 bytes assets/images/ic_youtube_logo.png | Bin 0 -> 417 bytes ios/Runner/Info.plist | 4 +++ lib/core/common/config.dart | 4 ++- lib/gen/assets.gen.dart | 5 ++++ lib/l10n/intl_en.arb | 4 ++- lib/ui/common/app_base_button.dart | 15 +++++++++- lib/ui/common/app_primary_button.dart | 3 ++ lib/ui/helper/launch_helper.dart | 27 +++++++++++++++++ lib/ui/videos/videos.dart | 35 +++++++++++++++++------ 14 files changed, 92 insertions(+), 11 deletions(-) create mode 100644 assets/images/1.5x/ic_youtube_logo.png create mode 100644 assets/images/2.0x/ic_youtube_logo.png create mode 100644 assets/images/3.0x/ic_youtube_logo.png create mode 100644 assets/images/4.0x/ic_youtube_logo.png create mode 100644 assets/images/ic_youtube_logo.png create mode 100644 lib/ui/helper/launch_helper.dart diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 34e0766..d261653 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -34,9 +34,15 @@ + + + 329 + + + \ No newline at end of file diff --git a/assets/images/1.5x/ic_youtube_logo.png b/assets/images/1.5x/ic_youtube_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..96ff2e3d73654dd2e8d47255dd959f3659773ae0 GIT binary patch literal 567 zcmV-70?7S|P)X1^@s6RQmj^00009a7bBm000o2 z000o20Vd5lGynhq0drDELIAGL9O(c600d`2O+f$vv5yPg5U{`fjPJnuna)XK$MJ(DQ^a!m)QFo*_$c_bxhq0TK zmIY8Z!hDN3jy&@7j6E3>)(GpZrVgl~fEs}#2F3DOT12ZsL=iDZ_y!rDtcI8Gj8r;_ z1{NykNj4vh*KNo?>#aBps4s6#{2k+L@9i3sQEEEMJUoanG{g7(VcAjPS*z(m#HX0L zonJhny@{|8QNs#hMhu@2pPNRJLJeEOL@6plPS~*(B9fx5t+nnl_#Rb2$~r=A+1LpYdoD=rW+PA^c!7I6mu=9tq!BTQK z!q(XQCj#m*bA#XpmqOrxWY#D+ZTDTnunrXw3B{d>bmJ{-B^hF9*HQ_*tVdX50gp(v zmzY*5MHBdhX=;Tqu~#9o(e3;ydp1QZkKqHxs4SvwX3cWkcn~wrG1xt7f@Q zu#RQ-)KFX-ifct_5aS2FTqja2bCvy;gQiNh!!i>8kPk{-tUNFFI@kaJ002ovPDHLk FV1gp7_8!Ms2#wMpuRyz*HiKY$=FVHo+QbV80gYBD7t0TUm^ z9G*bliyypJxhHTe-%r3iXU;>Fa=iHUHLQPwsyBOs@ktI$Hu?EBC_2b|mfcP-mTfD8 zz5e)IdU=EvBA&mt9=h!9R77^>3srA*dG2mRC<_`S}yu*B)j%?|D#C)tPTJF z(46Crnu}Y2Eg;!^tfb};V@HrEyHifLgO*{YP-VzM>6zm}qPw*~vU7 j6`N}X6)tYC9tpxffq?Xcrz=GM00000NkvXXu0mjf1rIwT literal 0 HcmV?d00001 diff --git a/assets/images/3.0x/ic_youtube_logo.png b/assets/images/3.0x/ic_youtube_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..a577dd303b70a9938294378dbe5bb18eb6376560 GIT binary patch literal 930 zcmV;T16}-yP)!o}kpOqiFnoirMa)Wnp6RKi4wVopG`M3B9} zOmd85bVkA$mxstX#GK6Aq@3TMtfR|y3{Av(*f!3_=djVlO2<+@KkfE02Q=%8c(v0) zM9-zzl8a7nasdI-V^EKBbC8{OkIQ~AEySbk^_cjrlv-Foti|LxZ(_nyt_aas+j?P$ z-re!LKM&$M+2-Knuvb)E2(j8ppQlGsIL&<)NWOro!3|dN78(_y{v4g zjG8k5ZzyGI*;`zN*p8bPK8m~+8#;&(ek?)+f9XCYBg(1~A(j;>EW;D|Nq654co=+u zz)1mFf!F#n6~2A-4%!41lgtN$B|27UN|oExOo zyTLTlYn&+}^760@d6Ajq@t}+fZ&uki;;wy_54eY#qq3~8&}>#3M})xO$6-&Qx35E7 zbnyo{j~M1hFg~NEFwBJzQ2Yrsg>txg(Q&sPuXT>(u!S1oaxP^W(3Zzjb;N3SI5$xb zWSLL9#M2Q`Q80hL{GtbIza_wGW5KZ^C}Vcb_ltDo>4@~0drDELIAGL9O(c600d`2O+f$vv5yPmAK^qz9qD$ojbr%KFZt9#Mxk2O;1UW(7O{@Y1>KoL( z0gJ?L76qd03}g`oC>jNx;p-cI$P!IEicCQ>?ECdfTvIx z*~ueVsFazV@SqdjWn?hvvL@*EH?}M3T=n6z)! zbX4?M>1>mLeufUf_Fx3I%!7H5L>~^f`HR2TG{@!=WFiMfH}-ij+d&}3BaYZD*X-adlvXzyb|CP6Ah6$+WxL4NH@o`52wN;J zbcKwAS7^`)c$NYOODZ4>x|7Xl84|^d+Pf4jNreX|yQaKVC)P#S z0CyVptNlq{1Oo1Yrxmn@Nk-A6q)hhe>9P3q3sd9ZYw#=%;ZF9~-q{E?D0yW7<<-x# z5Q#c^GMGLwn>xi_tk$mF0Wb0*Budk_^^?JwX2;1m`|PV<1nG6~b}=6WkJZ0#@4?@{ z9@n3`cqrHmeg`n%3*e97nSppFh)2s3lOn60onOat{^Fn?hrNuj7XaNhi#vEaB<@Of z{QID?FsPY^&x?cdjhXsqoXk_1_41P$EPfbBcYOl)K76*CcO@!g`{g*SZ4T|TbYNx#Ie|vf15yk%};Q#;t07*qoM6N<$ Ef}#ddhyVZp literal 0 HcmV?d00001 diff --git a/assets/images/ic_youtube_logo.png b/assets/images/ic_youtube_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..d077b481da486880dac9c2a1ec975df141b31416 GIT binary patch literal 417 zcmV;S0bc%zP)TBw(qzAfy%3_A8T**X3KN3d2;>z5 zP-AhODy?$(*gR;(Cw;QFMqmt~4)8V+k;kq8!;JrbV!p5*k7-g2Ae}DeNNA-Qmm zOX@rv{?4UmCo3H-(F61BlW~@upMF7l6uE^!1*`qGLl?a-4kHB<%MN2B*l}6nW$4L@ zdm=9@SvSS4uT5EM3(cBI^7f7uRgZ0<`(CuVLLWJ*>btCHZT + LSApplicationQueriesSchemes + + youtube + CADisableMinimumFrameDurationOnPhone CFBundleDevelopmentRegion diff --git a/lib/core/common/config.dart b/lib/core/common/config.dart index b4ede7c..cdf29de 100644 --- a/lib/core/common/config.dart +++ b/lib/core/common/config.dart @@ -42,8 +42,10 @@ abstract class Config { static Uri imagesTipsRepository = Uri.parse('https://www.github.com/vandadnp/flutter-tips-and-tricks'); + static String widgetOfTheWeekPlaylistId = + 'PLjxrf2q8roU23XGwz3Km7sQZFTdB996iG'; static Uri widgetOfTheWeekLink = Uri.parse( - 'https://www.youtube.com/watch?v=b6Z885Z46cU&list=PLjxrf2q8roU23XGwz3Km7sQZFTdB996iG', + 'https://www.youtube.com/playlist?list=$widgetOfTheWeekPlaylistId', ); static String fluttipsRepository = 'https://github.com/xmartlabs/fluttips'; static Uri xmartlabsLinkedln = diff --git a/lib/gen/assets.gen.dart b/lib/gen/assets.gen.dart index 8854d1f..69c4b5c 100644 --- a/lib/gen/assets.gen.dart +++ b/lib/gen/assets.gen.dart @@ -32,6 +32,10 @@ class $AssetsImagesGen { AssetGenImage get icTwitterLogo => const AssetGenImage('assets/images/ic_twitter_logo.png'); + /// File path: assets/images/ic_youtube_logo.png + AssetGenImage get icYoutubeLogo => + const AssetGenImage('assets/images/ic_youtube_logo.png'); + /// File path: assets/images/onboarding_branding.png AssetGenImage get onboardingBranding => const AssetGenImage('assets/images/onboarding_branding.png'); @@ -59,6 +63,7 @@ class $AssetsImagesGen { icInstagramLogo, icLinkedlnLogo, icTwitterLogo, + icYoutubeLogo, onboardingBranding, onboardingDescribeApp, onboardingFavourite, diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index adc3433..bffe969 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -64,6 +64,8 @@ "password": "Password", "search": "Search", "secondMessageEmptyFavoritesScreen": "2. Tap on the start icon on the bottom right of the screen", - "videos": "Coming soon", + "videos": "Videos", + "videos_button": "Watch videos", + "videos_description": "Here you have series of quick, animated videos, each of which covers a particular widget from the Flutter SDK.\n\nWe’re working to improve this feature :)", "xmartlabs_projects": "Xmartlabs' projects" } \ No newline at end of file diff --git a/lib/ui/common/app_base_button.dart b/lib/ui/common/app_base_button.dart index 1d31ca1..58f64d5 100644 --- a/lib/ui/common/app_base_button.dart +++ b/lib/ui/common/app_base_button.dart @@ -8,12 +8,14 @@ class AppBaseButton extends StatelessWidget { final VoidCallback action; final Color backgroundColor; final Color textColor; + final Image? image; const AppBaseButton({ required this.text, required this.action, required this.backgroundColor, required this.textColor, + this.image, Key? key, }) : super(key: key); @@ -29,6 +31,17 @@ class AppBaseButton extends StatelessWidget { color: backgroundColor, textColor: textColor, onPressed: action, - child: Text(text), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + if (image != null) + Container( + padding: EdgeInsets.only(right: 10.w), + child: image, + ), + Text(text), + ], + ), ); } diff --git a/lib/ui/common/app_primary_button.dart b/lib/ui/common/app_primary_button.dart index 6d6b6c9..a012bbf 100644 --- a/lib/ui/common/app_primary_button.dart +++ b/lib/ui/common/app_primary_button.dart @@ -6,10 +6,12 @@ import 'package:fluttips/ui/theme/app_theme.dart'; class AppPrimaryButton extends StatelessWidget { final String text; final VoidCallback action; + final Image? image; const AppPrimaryButton({ required this.text, required this.action, + this.image, Key? key, }) : super(key: key); @@ -17,6 +19,7 @@ class AppPrimaryButton extends StatelessWidget { Widget build(BuildContext context) => AppBaseButton( text: text, action: action, + image: image, backgroundColor: context.theme.colors.primary.shade100, textColor: context.theme.colors.primary, ); diff --git a/lib/ui/helper/launch_helper.dart b/lib/ui/helper/launch_helper.dart new file mode 100644 index 0000000..ab6aa3f --- /dev/null +++ b/lib/ui/helper/launch_helper.dart @@ -0,0 +1,27 @@ +import 'dart:io'; +import 'package:url_launcher/url_launcher.dart'; + +Future openYoutubePlaylist(String playlistId) async { + final url = 'www.youtube.com/playlist?list=$playlistId'; + final youtubeWebUri = Uri.parse('https://$url'); + if (Platform.isIOS) { + if (await canLaunchUrl(Uri.parse('youtube://$url'))) { + await launchUrl( + Uri.parse('youtube://$url'), + mode: LaunchMode.externalApplication, + ); + } else { + if (await canLaunchUrl(youtubeWebUri)) { + await launchUrl(youtubeWebUri); + } else { + throw Exception('Could not launch https://$url'); + } + } + } else { + if (await canLaunchUrl(youtubeWebUri)) { + await launchUrl(youtubeWebUri); + } else { + throw Exception('Could not launch https://$url'); + } + } +} diff --git a/lib/ui/videos/videos.dart b/lib/ui/videos/videos.dart index e523724..4c28ac1 100644 --- a/lib/ui/videos/videos.dart +++ b/lib/ui/videos/videos.dart @@ -1,7 +1,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:fluttips/ui/common/app_primary_button.dart'; import 'package:fluttips/ui/common/context_extensions.dart'; +import 'package:fluttips/ui/helper/launch_helper.dart'; import 'package:fluttips/ui/theme/app_theme.dart'; +import 'package:fluttips/gen/assets.gen.dart'; +import 'package:fluttips/core/common/config.dart'; class VideosScreen extends StatelessWidget { const VideosScreen({Key? key}) : super(key: key); @@ -12,21 +16,36 @@ class VideosScreen extends StatelessWidget { class _VideosContentScreen extends StatelessWidget { @override - Widget build(BuildContext context) => Center( + Widget build(BuildContext context) => Container( + padding: EdgeInsets.fromLTRB(70.w, 30.h, 70.w, 30.h), + margin: EdgeInsets.only(right: 30.w, left: 20.w), child: Column( - mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( context.localizations.videos, - style: context.theme.textStyles.titleLarge!.copyWith( - color: context.theme.colors.surface.shade700, + style: context.theme.textStyles.headlineLarge!.copyWith( + color: context.theme.colors.surface, fontWeight: FontWeight.bold, ), + textDirection: TextDirection.ltr, ), - SizedBox(height: 10.h), - Icon( - Icons.play_circle_outline_outlined, - color: context.theme.colors.surface.shade700, + SizedBox(height: 20.h), + Text( + context.localizations.videos_description, + style: context.theme.textStyles.bodyLarge!.copyWith( + color: context.theme.colors.surface, + ), + textDirection: TextDirection.ltr, + ), + SizedBox(height: 20.h), + Divider(color: context.theme.colors.surface.shade700), + SizedBox(height: 30.h), + AppPrimaryButton( + image: Assets.images.icYoutubeLogo.image(), + text: context.localizations.videos_button, + action: () => + openYoutubePlaylist(Config.widgetOfTheWeekPlaylistId), ), ], ),