From 4fc5ef8da31b4dadbefab8fb9938ff4e8df5b79d Mon Sep 17 00:00:00 2001 From: RuiAlonso Date: Tue, 21 Nov 2023 12:30:21 +0100 Subject: [PATCH 1/9] feat: first iteration initial screen --- assets/icons/arrow_forward.png | Bin 0 -> 196 bytes assets/icons/asterisk.png | Bin 0 -> 300 bytes lib/app/view/app.dart | 3 +- lib/home/home.dart | 1 + lib/home/view/home_page.dart | 92 +++++++++++++++++++++++++++++++++ pubspec.yaml | 3 ++ 6 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 assets/icons/arrow_forward.png create mode 100644 assets/icons/asterisk.png create mode 100644 lib/home/home.dart create mode 100644 lib/home/view/home_page.dart diff --git a/assets/icons/arrow_forward.png b/assets/icons/arrow_forward.png new file mode 100644 index 0000000000000000000000000000000000000000..00caafe03eb907ec67e70d0a47da2eba219f187c GIT binary patch literal 196 zcmeAS@N?(olHy`uVBq!ia0vp^l0YoM!3HGxw}u@9Qk(@Ik;M!Q+`=Ht$S`Y;1W=H% zILO_JVcj{Imp~3nx}&cn1H;CC?mvmFKz^jBi(^Oy``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eB{y|R{$B+ufqmv!^nhXS7>p6S9J@&ZAR&keC zdEBjJDc5^x>vPJlafwl8)-At49`3qBi{}39Kl3NV#yWeW1FP68?FYY@@?`%p&qz?X zdz>M;p5fNU#QzMl=9#}bcs0m_Wd%#Y%En-6=Myz1>%zJv6pAz}4zDYDo>q_++Vqln zLF>yW>r33Na*{Srde_%$5dKhNv%5w3lW4kJ;UJX>gTe~DWM4fd3|qa literal 0 HcmV?d00001 diff --git a/lib/app/view/app.dart b/lib/app/view/app.dart index 246797c..177af41 100644 --- a/lib/app/view/app.dart +++ b/lib/app/view/app.dart @@ -1,5 +1,6 @@ import 'package:api_client/api_client.dart'; import 'package:dash_ai_search/counter/counter.dart'; +import 'package:dash_ai_search/home/home.dart'; import 'package:dash_ai_search/l10n/l10n.dart'; import 'package:flutter/material.dart'; @@ -22,7 +23,7 @@ class App extends StatelessWidget { ), localizationsDelegates: AppLocalizations.localizationsDelegates, supportedLocales: AppLocalizations.supportedLocales, - home: const CounterPage(), + home: const HomePage(), ); } } diff --git a/lib/home/home.dart b/lib/home/home.dart new file mode 100644 index 0000000..acd3393 --- /dev/null +++ b/lib/home/home.dart @@ -0,0 +1 @@ +export 'view/home_page.dart'; diff --git a/lib/home/view/home_page.dart b/lib/home/view/home_page.dart new file mode 100644 index 0000000..3fdd51b --- /dev/null +++ b/lib/home/view/home_page.dart @@ -0,0 +1,92 @@ +import 'package:dash_ai_search/l10n/l10n.dart'; +import 'package:flutter/material.dart'; + +class HomePage extends StatelessWidget { + const HomePage({super.key}); + + @override + Widget build(BuildContext context) { + final l10n = context.l10n; + + return Scaffold( + backgroundColor: const Color(0xFFBAC4E1), + body: Stack( + children: [ + const Positioned( + top: 40, + left: 48, + child: Row( + children: [ + Text( + 'Vertex AI', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w400, + color: Colors.black, + ), + ), + Image( + image: AssetImage('assets/asterisk.png'), + ), + Text( + 'Flutter', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w400, + color: Colors.black, + ), + ), + ], + )), + Center( + child: SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text( + 'Ask a question, get \nthe right answer, with \nGoogle Vertex AI', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 72, + fontWeight: FontWeight.w700, + color: Color(0xFF020F30), + ), + ), + const SizedBox(height: 40), + TextButton.icon( + icon: const Image( + image: AssetImage('assets/arrow_forward.png'), + ), + label: const Text( + 'Start asking', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + color: Colors.white, + ), + ), + style: const ButtonStyle( + backgroundColor: MaterialStatePropertyAll( + Color(0xFF0273E6), + ), + padding: MaterialStatePropertyAll( + EdgeInsets.only( + left: 24, + top: 20, + bottom: 20, + right: 32, + ), + ), + ), + onPressed: () {}, + ), + ], + ), + ), + ), + ], + ), + ); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 981ffcd..bf33956 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -28,3 +28,6 @@ dev_dependencies: flutter: uses-material-design: true generate: true + assets: + - assets/ + - assets/icons From 2fab8fe4713e5d3fb743989d03c3367ab3ead0f7 Mon Sep 17 00:00:00 2001 From: RuiAlonso Date: Tue, 21 Nov 2023 21:23:34 +0100 Subject: [PATCH 2/9] feat: homepage with initial screen and basic ui --- devtools_options.yaml | 1 + lib/app/view/app.dart | 1 - lib/counter/counter.dart | 2 - lib/counter/cubit/counter_cubit.dart | 8 -- lib/counter/view/counter_page.dart | 55 -------- lib/gen/assets.gen.dart | 105 +++++++++++++++ lib/home/home.dart | 1 + lib/home/view/home_page.dart | 84 +----------- lib/home/widgets/background.dart | 127 ++++++++++++++++++ lib/home/widgets/initial_screen.dart | 38 ++++++ lib/home/widgets/logo.dart | 40 ++++++ lib/home/widgets/next_button.dart | 44 ++++++ lib/home/widgets/widgets.dart | 4 + lib/l10n/arb/app_en.arb | 18 ++- lib/l10n/arb/app_es.arb | 7 - pubspec.lock | 192 +++++++++++++++++++++++++++ pubspec.yaml | 8 +- test/home/view/home_page_test.dart | 7 + 18 files changed, 586 insertions(+), 156 deletions(-) create mode 100644 devtools_options.yaml delete mode 100644 lib/counter/counter.dart delete mode 100644 lib/counter/cubit/counter_cubit.dart delete mode 100644 lib/counter/view/counter_page.dart create mode 100644 lib/gen/assets.gen.dart create mode 100644 lib/home/widgets/background.dart create mode 100644 lib/home/widgets/initial_screen.dart create mode 100644 lib/home/widgets/logo.dart create mode 100644 lib/home/widgets/next_button.dart create mode 100644 lib/home/widgets/widgets.dart delete mode 100644 lib/l10n/arb/app_es.arb create mode 100644 test/home/view/home_page_test.dart diff --git a/devtools_options.yaml b/devtools_options.yaml new file mode 100644 index 0000000..7e7e7f6 --- /dev/null +++ b/devtools_options.yaml @@ -0,0 +1 @@ +extensions: diff --git a/lib/app/view/app.dart b/lib/app/view/app.dart index 177af41..47e10f4 100644 --- a/lib/app/view/app.dart +++ b/lib/app/view/app.dart @@ -1,5 +1,4 @@ import 'package:api_client/api_client.dart'; -import 'package:dash_ai_search/counter/counter.dart'; import 'package:dash_ai_search/home/home.dart'; import 'package:dash_ai_search/l10n/l10n.dart'; import 'package:flutter/material.dart'; diff --git a/lib/counter/counter.dart b/lib/counter/counter.dart deleted file mode 100644 index cc3f0c5..0000000 --- a/lib/counter/counter.dart +++ /dev/null @@ -1,2 +0,0 @@ -export 'cubit/counter_cubit.dart'; -export 'view/counter_page.dart'; diff --git a/lib/counter/cubit/counter_cubit.dart b/lib/counter/cubit/counter_cubit.dart deleted file mode 100644 index 70bd952..0000000 --- a/lib/counter/cubit/counter_cubit.dart +++ /dev/null @@ -1,8 +0,0 @@ -import 'package:bloc/bloc.dart'; - -class CounterCubit extends Cubit { - CounterCubit() : super(0); - - void increment() => emit(state + 1); - void decrement() => emit(state - 1); -} diff --git a/lib/counter/view/counter_page.dart b/lib/counter/view/counter_page.dart deleted file mode 100644 index 422e6ab..0000000 --- a/lib/counter/view/counter_page.dart +++ /dev/null @@ -1,55 +0,0 @@ -import 'package:dash_ai_search/counter/counter.dart'; -import 'package:dash_ai_search/l10n/l10n.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; - -class CounterPage extends StatelessWidget { - const CounterPage({super.key}); - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (_) => CounterCubit(), - child: const CounterView(), - ); - } -} - -class CounterView extends StatelessWidget { - const CounterView({super.key}); - - @override - Widget build(BuildContext context) { - final l10n = context.l10n; - return Scaffold( - appBar: AppBar(title: Text(l10n.counterAppBarTitle)), - body: const Center(child: CounterText()), - floatingActionButton: Column( - mainAxisAlignment: MainAxisAlignment.end, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - FloatingActionButton( - onPressed: () => context.read().increment(), - child: const Icon(Icons.add), - ), - const SizedBox(height: 8), - FloatingActionButton( - onPressed: () => context.read().decrement(), - child: const Icon(Icons.remove), - ), - ], - ), - ); - } -} - -class CounterText extends StatelessWidget { - const CounterText({super.key}); - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - final count = context.select((CounterCubit cubit) => cubit.state); - return Text('$count', style: theme.textTheme.displayLarge); - } -} diff --git a/lib/gen/assets.gen.dart b/lib/gen/assets.gen.dart new file mode 100644 index 0000000..42f4e15 --- /dev/null +++ b/lib/gen/assets.gen.dart @@ -0,0 +1,105 @@ +/// GENERATED CODE - DO NOT MODIFY BY HAND +/// ***************************************************** +/// FlutterGen +/// ***************************************************** + +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: directives_ordering,unnecessary_import,implicit_dynamic_list_literal,deprecated_member_use + +import 'package:flutter/widgets.dart'; + +class $AssetsIconsGen { + const $AssetsIconsGen(); + + /// File path: assets/icons/arrow_forward.png + AssetGenImage get arrowForward => + const AssetGenImage('assets/icons/arrow_forward.png'); + + /// File path: assets/icons/asterisk.png + AssetGenImage get asterisk => + const AssetGenImage('assets/icons/asterisk.png'); + + /// List of all assets + List get values => [arrowForward, asterisk]; +} + +class Assets { + Assets._(); + + static const $AssetsIconsGen icons = $AssetsIconsGen(); +} + +class AssetGenImage { + const AssetGenImage(this._assetName); + + final String _assetName; + + Image image({ + Key? key, + AssetBundle? bundle, + ImageFrameBuilder? frameBuilder, + ImageErrorWidgetBuilder? errorBuilder, + String? semanticLabel, + bool excludeFromSemantics = false, + double? scale, + double? width, + double? height, + Color? color, + Animation? opacity, + BlendMode? colorBlendMode, + BoxFit? fit, + AlignmentGeometry alignment = Alignment.center, + ImageRepeat repeat = ImageRepeat.noRepeat, + Rect? centerSlice, + bool matchTextDirection = false, + bool gaplessPlayback = false, + bool isAntiAlias = false, + String? package, + FilterQuality filterQuality = FilterQuality.low, + int? cacheWidth, + int? cacheHeight, + }) { + return Image.asset( + _assetName, + key: key, + bundle: bundle, + frameBuilder: frameBuilder, + errorBuilder: errorBuilder, + semanticLabel: semanticLabel, + excludeFromSemantics: excludeFromSemantics, + scale: scale, + width: width, + height: height, + color: color, + opacity: opacity, + colorBlendMode: colorBlendMode, + fit: fit, + alignment: alignment, + repeat: repeat, + centerSlice: centerSlice, + matchTextDirection: matchTextDirection, + gaplessPlayback: gaplessPlayback, + isAntiAlias: isAntiAlias, + package: package, + filterQuality: filterQuality, + cacheWidth: cacheWidth, + cacheHeight: cacheHeight, + ); + } + + ImageProvider provider({ + AssetBundle? bundle, + String? package, + }) { + return AssetImage( + _assetName, + bundle: bundle, + package: package, + ); + } + + String get path => _assetName; + + String get keyName => _assetName; +} diff --git a/lib/home/home.dart b/lib/home/home.dart index acd3393..4434705 100644 --- a/lib/home/home.dart +++ b/lib/home/home.dart @@ -1 +1,2 @@ export 'view/home_page.dart'; +export 'widgets/widgets.dart'; diff --git a/lib/home/view/home_page.dart b/lib/home/view/home_page.dart index 3fdd51b..24e3339 100644 --- a/lib/home/view/home_page.dart +++ b/lib/home/view/home_page.dart @@ -1,4 +1,4 @@ -import 'package:dash_ai_search/l10n/l10n.dart'; +import 'package:dash_ai_search/home/home.dart'; import 'package:flutter/material.dart'; class HomePage extends StatelessWidget { @@ -6,85 +6,13 @@ class HomePage extends StatelessWidget { @override Widget build(BuildContext context) { - final l10n = context.l10n; - - return Scaffold( - backgroundColor: const Color(0xFFBAC4E1), + return const Scaffold( + backgroundColor: Color(0xFFF8FAFF), body: Stack( children: [ - const Positioned( - top: 40, - left: 48, - child: Row( - children: [ - Text( - 'Vertex AI', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w400, - color: Colors.black, - ), - ), - Image( - image: AssetImage('assets/asterisk.png'), - ), - Text( - 'Flutter', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w400, - color: Colors.black, - ), - ), - ], - )), - Center( - child: SingleChildScrollView( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text( - 'Ask a question, get \nthe right answer, with \nGoogle Vertex AI', - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 72, - fontWeight: FontWeight.w700, - color: Color(0xFF020F30), - ), - ), - const SizedBox(height: 40), - TextButton.icon( - icon: const Image( - image: AssetImage('assets/arrow_forward.png'), - ), - label: const Text( - 'Start asking', - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w500, - color: Colors.white, - ), - ), - style: const ButtonStyle( - backgroundColor: MaterialStatePropertyAll( - Color(0xFF0273E6), - ), - padding: MaterialStatePropertyAll( - EdgeInsets.only( - left: 24, - top: 20, - bottom: 20, - right: 32, - ), - ), - ), - onPressed: () {}, - ), - ], - ), - ), - ), + Background(), + Logo(), + InitialScreen(), ], ), ); diff --git a/lib/home/widgets/background.dart b/lib/home/widgets/background.dart new file mode 100644 index 0000000..10ac072 --- /dev/null +++ b/lib/home/widgets/background.dart @@ -0,0 +1,127 @@ +import 'package:flutter/material.dart'; + +class Background extends StatelessWidget { + const Background({super.key}); + + @override + Widget build(BuildContext context) { + const leftOffset = -50.0; + const radius = 303.0; + const diameter = radius * 2; + + return const Positioned( + top: 0, + bottom: 0, + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + children: [ + _Circle( + offset: Offset(leftOffset, 0), + ), + _Circle( + offset: Offset(diameter + leftOffset, 0), + child: _Circle( + offset: Offset(diameter + leftOffset, 0), + radius: 255, + borderColor: Color(0xFFBAC4E1), + child: _Circle( + offset: Offset(diameter + leftOffset, 0), + radius: 185, + borderColor: Color(0xFFBAC4E1), + dotted: true, + ), + ), + ), + _Circle( + offset: Offset(diameter * 2 + leftOffset, 0), + ), + _Circle( + offset: Offset(diameter * 3 + leftOffset, 0), + ), + ], + ), + ), + ); + } +} + +class _Circle extends StatelessWidget { + const _Circle({ + this.offset = Offset.zero, + this.radius = 303, + this.borderColor = Colors.white, + this.dotted = false, + this.child, + }); + + final Offset offset; + final double radius; + final Color borderColor; + final bool dotted; + final Widget? child; + + @override + Widget build(BuildContext context) { + return CustomPaint( + painter: CirclePainter( + offset: offset, + radius: radius, + borderColor: borderColor, + dotted: dotted, + ), + child: child, + ); + } +} + +class CirclePainter extends CustomPainter { + CirclePainter({ + required this.offset, + required this.radius, + required this.borderColor, + required this.dotted, + }) { + _paintCircle = Paint() + ..color = Colors.white + ..style = PaintingStyle.fill; + _paintBorder = Paint() + ..color = borderColor + ..strokeWidth = 1 + ..style = PaintingStyle.stroke; + } + + final Offset offset; + final double radius; + final Color borderColor; + final bool dotted; + + late final Paint _paintCircle; + late final Paint _paintBorder; + + @override + void paint(Canvas canvas, Size size) { + canvas.drawCircle( + offset, + radius, + _paintCircle, + ); + + if (dotted) { + canvas.drawCircle( + offset, + radius, + _paintBorder, + ); + } else { + canvas.drawCircle( + offset, + radius, + _paintBorder, + ); + } + } + + @override + bool shouldRepaint(CustomPainter oldDelegate) => false; +} diff --git a/lib/home/widgets/initial_screen.dart b/lib/home/widgets/initial_screen.dart new file mode 100644 index 0000000..53067b3 --- /dev/null +++ b/lib/home/widgets/initial_screen.dart @@ -0,0 +1,38 @@ +import 'package:dash_ai_search/gen/assets.gen.dart'; +import 'package:dash_ai_search/home/home.dart'; +import 'package:dash_ai_search/l10n/l10n.dart'; +import 'package:flutter/material.dart'; + +class InitialScreen extends StatelessWidget { + const InitialScreen({super.key}); + + @override + Widget build(BuildContext context) { + final l10n = context.l10n; + + return Center( + child: SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + l10n.initialScreenTitle, + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 72, + fontWeight: FontWeight.w700, + color: Color(0xFF020F30), + ), + ), + const SizedBox(height: 40), + NextButton( + icon: Assets.icons.arrowForward.image(), + label: l10n.startAsking, + onPressed: () {}, + ), + ], + ), + ), + ); + } +} diff --git a/lib/home/widgets/logo.dart b/lib/home/widgets/logo.dart new file mode 100644 index 0000000..47f9a00 --- /dev/null +++ b/lib/home/widgets/logo.dart @@ -0,0 +1,40 @@ +import 'package:dash_ai_search/gen/assets.gen.dart'; +import 'package:dash_ai_search/l10n/l10n.dart'; +import 'package:flutter/material.dart'; + +class Logo extends StatelessWidget { + const Logo({super.key}); + + @override + Widget build(BuildContext context) { + final l10n = context.l10n; + + return Positioned( + top: 40, + left: 48, + child: Row( + children: [ + Text( + l10n.vertexAI, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w400, + color: Colors.black, + ), + ), + const SizedBox(width: 4), + Assets.icons.asterisk.image(), + const SizedBox(width: 4), + Text( + l10n.flutter, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w400, + color: Colors.black, + ), + ), + ], + ), + ); + } +} diff --git a/lib/home/widgets/next_button.dart b/lib/home/widgets/next_button.dart new file mode 100644 index 0000000..a2d270d --- /dev/null +++ b/lib/home/widgets/next_button.dart @@ -0,0 +1,44 @@ +import 'package:flutter/material.dart'; + +class NextButton extends StatelessWidget { + const NextButton({ + required this.icon, + required this.label, + required this.onPressed, + super.key, + }); + + final Image icon; + final String label; + final VoidCallback onPressed; + + @override + Widget build(BuildContext context) { + return TextButton.icon( + icon: icon, + label: Text( + label, + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + color: Colors.white, + ), + ), + style: const ButtonStyle( + backgroundColor: MaterialStatePropertyAll( + Color(0xFF0273E6), + ), + padding: MaterialStatePropertyAll( + EdgeInsets.only( + left: 24, + top: 20, + bottom: 20, + right: 32, + ), + ), + ), + onPressed: onPressed, + ); + } +} diff --git a/lib/home/widgets/widgets.dart b/lib/home/widgets/widgets.dart new file mode 100644 index 0000000..2e6a36c --- /dev/null +++ b/lib/home/widgets/widgets.dart @@ -0,0 +1,4 @@ +export 'background.dart'; +export 'initial_screen.dart'; +export 'logo.dart'; +export 'next_button.dart'; diff --git a/lib/l10n/arb/app_en.arb b/lib/l10n/arb/app_en.arb index a5484a0..364c612 100644 --- a/lib/l10n/arb/app_en.arb +++ b/lib/l10n/arb/app_en.arb @@ -1,7 +1,19 @@ { "@@locale": "en", - "counterAppBarTitle": "Counter", - "@counterAppBarTitle": { - "description": "Text shown in the AppBar of the Counter Page" + "vertexAI": "Vertex AI", + "@vertexAI": { + "description": "Vertex AI text on logo" + }, + "flutter": "Flutter", + "@flutter": { + "description": "Flutter text on logo" + }, + "initialScreenTitle": "Ask a question, get \nthe right answer, with \nGoogle Vertex AI", + "@initialScreenTitle": { + "description": "Title shown on Initial screen" + }, + "startAsking": "Start asking", + "@startAsking": { + "description": "Button text for start asking" } } \ No newline at end of file diff --git a/lib/l10n/arb/app_es.arb b/lib/l10n/arb/app_es.arb deleted file mode 100644 index f1405f0..0000000 --- a/lib/l10n/arb/app_es.arb +++ /dev/null @@ -1,7 +0,0 @@ -{ - "@@locale": "es", - "counterAppBarTitle": "Contador", - "@counterAppBarTitle": { - "description": "Texto mostrado en la AppBar de la página del contador" - } -} \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index edc26bc..4d559b1 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -64,6 +64,70 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" + build: + dependency: transitive + description: + name: build + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + build_config: + dependency: transitive + description: + name: build_config + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + url: "https://pub.dev" + source: hosted + version: "1.1.1" + build_daemon: + dependency: transitive + description: + name: build_daemon + sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1" + url: "https://pub.dev" + source: hosted + version: "4.0.1" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + sha256: "64e12b0521812d1684b1917bc80945625391cb9bdd4312536b1d69dcb6133ed8" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + build_runner: + dependency: "direct dev" + description: + name: build_runner + sha256: "10c6bcdbf9d049a0b666702cf1cee4ddfdc38f02a19d35ae392863b47519848b" + url: "https://pub.dev" + source: hosted + version: "2.4.6" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + sha256: c9e32d21dd6626b5c163d48b037ce906bbe428bc23ab77bcd77bb21e593b6185 + url: "https://pub.dev" + source: hosted + version: "7.2.11" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: "723b4021e903217dfc445ec4cf5b42e27975aece1fc4ebbc1ca6329c2d9fb54e" + url: "https://pub.dev" + source: hosted + version: "8.7.0" characters: dependency: transitive description: @@ -72,6 +136,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff + url: "https://pub.dev" + source: hosted + version: "2.0.3" clock: dependency: transitive description: @@ -80,6 +152,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: b2151ce26a06171005b379ecff6e08d34c470180ffe16b8e14b6d52be292b55f + url: "https://pub.dev" + source: hosted + version: "4.8.0" collection: dependency: transitive description: @@ -88,6 +168,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.18.0" + color: + dependency: transitive + description: + name: color + sha256: ddcdf1b3badd7008233f5acffaf20ca9f5dc2cd0172b75f68f24526a5f5725cb + url: "https://pub.dev" + source: hosted + version: "3.0.0" convert: dependency: transitive description: @@ -112,6 +200,22 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.3" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: abd7625e16f51f554ea244d090292945ec4d4be7bfbaf2ec8cccea568919d334 + url: "https://pub.dev" + source: hosted + version: "2.3.3" + dartx: + dependency: transitive + description: + name: dartx + sha256: "8b25435617027257d43e6508b5fe061012880ddfdaa75a71d607c3de2a13d244" + url: "https://pub.dev" + source: hosted + version: "1.2.0" diff_match_patch: dependency: transitive description: @@ -136,6 +240,14 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.0" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" + source: hosted + version: "1.1.0" flutter: dependency: "direct main" description: flutter @@ -149,6 +261,22 @@ packages: url: "https://pub.dev" source: hosted version: "8.1.3" + flutter_gen_core: + dependency: transitive + description: + name: flutter_gen_core + sha256: "8b4ff1d45d125e576e26ea99d15e0419bb3c45b53696e022880866b78bb6b830" + url: "https://pub.dev" + source: hosted + version: "5.3.2" + flutter_gen_runner: + dependency: "direct dev" + description: + name: flutter_gen_runner + sha256: fd197f8c657e79313d53d3934de602ebe604ba722a84c88ae3a43cd90428c67a + url: "https://pub.dev" + source: hosted + version: "5.3.2" flutter_localizations: dependency: "direct main" description: flutter @@ -175,6 +303,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.2" + graphs: + dependency: transitive + description: + name: graphs + sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 + url: "https://pub.dev" + source: hosted + version: "2.3.1" http: dependency: transitive description: @@ -223,6 +359,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.7" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 + url: "https://pub.dev" + source: hosted + version: "4.8.1" logging: dependency: transitive description: @@ -303,6 +447,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.8.3" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: eeb2d1428ee7f4170e2bd498827296a18d4e7fc462b71727d111c0ac7707cfa6 + url: "https://pub.dev" + source: hosted + version: "6.0.1" pool: dependency: transitive description: @@ -327,6 +479,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367 + url: "https://pub.dev" + source: hosted + version: "1.2.3" shelf: dependency: transitive description: @@ -404,6 +564,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.2" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + url: "https://pub.dev" + source: hosted + version: "2.1.0" string_scanner: dependency: transitive description: @@ -444,6 +612,22 @@ packages: url: "https://pub.dev" source: hosted version: "0.5.9" + time: + dependency: transitive + description: + name: time + sha256: "83427e11d9072e038364a5e4da559e85869b227cf699a541be0da74f14140124" + url: "https://pub.dev" + source: hosted + version: "2.1.3" + timing: + dependency: transitive + description: + name: timing + sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + url: "https://pub.dev" + source: hosted + version: "1.0.1" typed_data: dependency: transitive description: @@ -508,6 +692,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.1" + xml: + dependency: transitive + description: + name: xml + sha256: af5e77e9b83f2f4adc5d3f0a4ece1c7f45a2467b695c2540381bac793e34e556 + url: "https://pub.dev" + source: hosted + version: "6.4.2" yaml: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index bf33956..a531115 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -20,14 +20,18 @@ dependencies: dev_dependencies: bloc_test: ^9.1.4 + build_runner: ^2.4.6 + flutter_gen_runner: ^5.3.2 flutter_test: sdk: flutter mocktail: ^1.0.0 very_good_analysis: ^5.1.0 +flutter_gen: + line_length: 80 # + flutter: uses-material-design: true generate: true assets: - - assets/ - - assets/icons + - assets/icons/ diff --git a/test/home/view/home_page_test.dart b/test/home/view/home_page_test.dart new file mode 100644 index 0000000..de7b110 --- /dev/null +++ b/test/home/view/home_page_test.dart @@ -0,0 +1,7 @@ +import 'package:flutter_test/flutter_test.dart'; + +void main() { + testWidgets('home page ...', (tester) async { + // TODO: Implement test + }); +} \ No newline at end of file From 08f494842a5b666d3fefd9e8a6691b15c49b5a48 Mon Sep 17 00:00:00 2001 From: RuiAlonso Date: Wed, 22 Nov 2023 09:36:00 +0100 Subject: [PATCH 3/9] test: tests coverage --- lib/home/view/home_page.dart | 12 +++- lib/home/widgets/background.dart | 58 ++++++++-------- .../{next_button.dart => cta_button.dart} | 8 +-- lib/home/widgets/initial_screen.dart | 3 +- lib/home/widgets/logo.dart | 44 ++++++------ lib/home/widgets/widgets.dart | 2 +- test/app/view/app_test.dart | 6 +- test/counter/cubit/counter_cubit_test.dart | 25 ------- test/counter/view/counter_page_test.dart | 67 ------------------- test/home/view/home_page_test.dart | 19 +++++- test/home/widgets/background_test.dart | 18 +++++ test/home/widgets/cta_button_test.dart | 40 +++++++++++ test/home/widgets/initial_screen_test.dart | 22 ++++++ test/home/widgets/logo_test.dart | 24 +++++++ 14 files changed, 188 insertions(+), 160 deletions(-) rename lib/home/widgets/{next_button.dart => cta_button.dart} (86%) delete mode 100644 test/counter/cubit/counter_cubit_test.dart delete mode 100644 test/counter/view/counter_page_test.dart create mode 100644 test/home/widgets/background_test.dart create mode 100644 test/home/widgets/cta_button_test.dart create mode 100644 test/home/widgets/initial_screen_test.dart create mode 100644 test/home/widgets/logo_test.dart diff --git a/lib/home/view/home_page.dart b/lib/home/view/home_page.dart index 24e3339..0c361a1 100644 --- a/lib/home/view/home_page.dart +++ b/lib/home/view/home_page.dart @@ -10,8 +10,16 @@ class HomePage extends StatelessWidget { backgroundColor: Color(0xFFF8FAFF), body: Stack( children: [ - Background(), - Logo(), + Positioned( + top: 0, + bottom: 0, + child: Background(), + ), + Positioned( + top: 40, + left: 48, + child: Logo(), + ), InitialScreen(), ], ), diff --git a/lib/home/widgets/background.dart b/lib/home/widgets/background.dart index 10ac072..8264b5f 100644 --- a/lib/home/widgets/background.dart +++ b/lib/home/widgets/background.dart @@ -9,50 +9,48 @@ class Background extends StatelessWidget { const radius = 303.0; const diameter = radius * 2; - return const Positioned( - top: 0, - bottom: 0, - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Row( - children: [ - _Circle( - offset: Offset(leftOffset, 0), - ), - _Circle( + return const SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + children: [ + Circle( + offset: Offset(leftOffset, 0), + ), + Circle( + offset: Offset(diameter + leftOffset, 0), + child: Circle( offset: Offset(diameter + leftOffset, 0), - child: _Circle( + radius: 255, + borderColor: Color(0xFFBAC4E1), + child: Circle( offset: Offset(diameter + leftOffset, 0), - radius: 255, + radius: 185, borderColor: Color(0xFFBAC4E1), - child: _Circle( - offset: Offset(diameter + leftOffset, 0), - radius: 185, - borderColor: Color(0xFFBAC4E1), - dotted: true, - ), + dotted: true, ), ), - _Circle( - offset: Offset(diameter * 2 + leftOffset, 0), - ), - _Circle( - offset: Offset(diameter * 3 + leftOffset, 0), - ), - ], - ), + ), + Circle( + offset: Offset(diameter * 2 + leftOffset, 0), + ), + Circle( + offset: Offset(diameter * 3 + leftOffset, 0), + ), + ], ), ); } } -class _Circle extends StatelessWidget { - const _Circle({ +class Circle extends StatelessWidget { + @visibleForTesting + const Circle({ this.offset = Offset.zero, this.radius = 303, this.borderColor = Colors.white, this.dotted = false, this.child, + super.key, }); final Offset offset; @@ -122,6 +120,8 @@ class CirclePainter extends CustomPainter { } } + // coverage:ignore-start @override bool shouldRepaint(CustomPainter oldDelegate) => false; + // coverage:ignore-end } diff --git a/lib/home/widgets/next_button.dart b/lib/home/widgets/cta_button.dart similarity index 86% rename from lib/home/widgets/next_button.dart rename to lib/home/widgets/cta_button.dart index a2d270d..085d091 100644 --- a/lib/home/widgets/next_button.dart +++ b/lib/home/widgets/cta_button.dart @@ -1,16 +1,16 @@ import 'package:flutter/material.dart'; -class NextButton extends StatelessWidget { - const NextButton({ +class CTAButton extends StatelessWidget { + const CTAButton({ required this.icon, required this.label, - required this.onPressed, + this.onPressed, super.key, }); final Image icon; final String label; - final VoidCallback onPressed; + final VoidCallback? onPressed; @override Widget build(BuildContext context) { diff --git a/lib/home/widgets/initial_screen.dart b/lib/home/widgets/initial_screen.dart index 53067b3..98a6280 100644 --- a/lib/home/widgets/initial_screen.dart +++ b/lib/home/widgets/initial_screen.dart @@ -25,10 +25,9 @@ class InitialScreen extends StatelessWidget { ), ), const SizedBox(height: 40), - NextButton( + CTAButton( icon: Assets.icons.arrowForward.image(), label: l10n.startAsking, - onPressed: () {}, ), ], ), diff --git a/lib/home/widgets/logo.dart b/lib/home/widgets/logo.dart index 47f9a00..6f265ad 100644 --- a/lib/home/widgets/logo.dart +++ b/lib/home/widgets/logo.dart @@ -9,32 +9,28 @@ class Logo extends StatelessWidget { Widget build(BuildContext context) { final l10n = context.l10n; - return Positioned( - top: 40, - left: 48, - child: Row( - children: [ - Text( - l10n.vertexAI, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.w400, - color: Colors.black, - ), + return Row( + children: [ + Text( + l10n.vertexAI, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w400, + color: Colors.black, ), - const SizedBox(width: 4), - Assets.icons.asterisk.image(), - const SizedBox(width: 4), - Text( - l10n.flutter, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.w400, - color: Colors.black, - ), + ), + const SizedBox(width: 4), + Assets.icons.asterisk.image(), + const SizedBox(width: 4), + Text( + l10n.flutter, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w400, + color: Colors.black, ), - ], - ), + ), + ], ); } } diff --git a/lib/home/widgets/widgets.dart b/lib/home/widgets/widgets.dart index 2e6a36c..1244f80 100644 --- a/lib/home/widgets/widgets.dart +++ b/lib/home/widgets/widgets.dart @@ -1,4 +1,4 @@ export 'background.dart'; +export 'cta_button.dart'; export 'initial_screen.dart'; export 'logo.dart'; -export 'next_button.dart'; diff --git a/test/app/view/app_test.dart b/test/app/view/app_test.dart index 8052a14..b4e958b 100644 --- a/test/app/view/app_test.dart +++ b/test/app/view/app_test.dart @@ -1,6 +1,6 @@ import 'package:api_client/api_client.dart'; import 'package:dash_ai_search/app/app.dart'; -import 'package:dash_ai_search/counter/counter.dart'; +import 'package:dash_ai_search/home/view/home_page.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -14,13 +14,13 @@ void main() { apiClient = _MockApiClient(); }); - testWidgets('renders CounterPage', (tester) async { + testWidgets('renders correctly', (tester) async { await tester.pumpWidget( App( apiClient: apiClient, ), ); - expect(find.byType(CounterPage), findsOneWidget); + expect(find.byType(HomePage), findsOneWidget); }); }); } diff --git a/test/counter/cubit/counter_cubit_test.dart b/test/counter/cubit/counter_cubit_test.dart deleted file mode 100644 index 2f649c1..0000000 --- a/test/counter/cubit/counter_cubit_test.dart +++ /dev/null @@ -1,25 +0,0 @@ -import 'package:bloc_test/bloc_test.dart'; -import 'package:dash_ai_search/counter/counter.dart'; -import 'package:flutter_test/flutter_test.dart'; - -void main() { - group('CounterCubit', () { - test('initial state is 0', () { - expect(CounterCubit().state, equals(0)); - }); - - blocTest( - 'emits [1] when increment is called', - build: CounterCubit.new, - act: (cubit) => cubit.increment(), - expect: () => [equals(1)], - ); - - blocTest( - 'emits [-1] when decrement is called', - build: CounterCubit.new, - act: (cubit) => cubit.decrement(), - expect: () => [equals(-1)], - ); - }); -} diff --git a/test/counter/view/counter_page_test.dart b/test/counter/view/counter_page_test.dart deleted file mode 100644 index 79ac31d..0000000 --- a/test/counter/view/counter_page_test.dart +++ /dev/null @@ -1,67 +0,0 @@ -import 'package:bloc_test/bloc_test.dart'; -import 'package:dash_ai_search/counter/counter.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:mocktail/mocktail.dart'; - -import '../../helpers/helpers.dart'; - -class MockCounterCubit extends MockCubit implements CounterCubit {} - -void main() { - group('CounterPage', () { - testWidgets('renders CounterView', (tester) async { - await tester.pumpApp(const CounterPage()); - expect(find.byType(CounterView), findsOneWidget); - }); - }); - - group('CounterView', () { - late CounterCubit counterCubit; - - setUp(() { - counterCubit = MockCounterCubit(); - }); - - testWidgets('renders current count', (tester) async { - const state = 42; - when(() => counterCubit.state).thenReturn(state); - await tester.pumpApp( - BlocProvider.value( - value: counterCubit, - child: const CounterView(), - ), - ); - expect(find.text('$state'), findsOneWidget); - }); - - testWidgets('calls increment when increment button is tapped', - (tester) async { - when(() => counterCubit.state).thenReturn(0); - when(() => counterCubit.increment()).thenReturn(null); - await tester.pumpApp( - BlocProvider.value( - value: counterCubit, - child: const CounterView(), - ), - ); - await tester.tap(find.byIcon(Icons.add)); - verify(() => counterCubit.increment()).called(1); - }); - - testWidgets('calls decrement when decrement button is tapped', - (tester) async { - when(() => counterCubit.state).thenReturn(0); - when(() => counterCubit.decrement()).thenReturn(null); - await tester.pumpApp( - BlocProvider.value( - value: counterCubit, - child: const CounterView(), - ), - ); - await tester.tap(find.byIcon(Icons.remove)); - verify(() => counterCubit.decrement()).called(1); - }); - }); -} diff --git a/test/home/view/home_page_test.dart b/test/home/view/home_page_test.dart index de7b110..271287a 100644 --- a/test/home/view/home_page_test.dart +++ b/test/home/view/home_page_test.dart @@ -1,7 +1,20 @@ +// ignore_for_file: prefer_const_constructors + +import 'package:dash_ai_search/home/home.dart'; import 'package:flutter_test/flutter_test.dart'; +import '../../helpers/helpers.dart'; + void main() { - testWidgets('home page ...', (tester) async { - // TODO: Implement test + group('HomePage', () { + testWidgets('renders correctly', (tester) async { + await tester.pumpApp( + HomePage(), + ); + + expect(find.byType(Background), findsOneWidget); + expect(find.byType(Logo), findsOneWidget); + expect(find.byType(InitialScreen), findsOneWidget); + }); }); -} \ No newline at end of file +} diff --git a/test/home/widgets/background_test.dart b/test/home/widgets/background_test.dart new file mode 100644 index 0000000..3957a3f --- /dev/null +++ b/test/home/widgets/background_test.dart @@ -0,0 +1,18 @@ +// ignore_for_file: prefer_const_constructors + +import 'package:dash_ai_search/home/home.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../../helpers/helpers.dart'; + +void main() { + group('Background', () { + testWidgets('renders correctly', (tester) async { + await tester.pumpApp( + Background(), + ); + + expect(find.byType(Circle), findsNWidgets(6)); + }); + }); +} diff --git a/test/home/widgets/cta_button_test.dart b/test/home/widgets/cta_button_test.dart new file mode 100644 index 0000000..5a944cb --- /dev/null +++ b/test/home/widgets/cta_button_test.dart @@ -0,0 +1,40 @@ +// ignore_for_file: prefer_const_constructors + +import 'package:dash_ai_search/gen/assets.gen.dart'; +import 'package:dash_ai_search/home/home.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../../helpers/helpers.dart'; + +void main() { + group('CTAButton', () { + testWidgets('renders correctly', (tester) async { + await tester.pumpApp( + CTAButton( + icon: Assets.icons.arrowForward.image(), + label: 'label', + onPressed: () {}, + ), + ); + + expect(find.text('label'), findsOneWidget); + }); + + testWidgets('calls onPressed when tap', (tester) async { + var called = false; + + await tester.pumpApp( + CTAButton( + icon: Assets.icons.arrowForward.image(), + label: 'label', + onPressed: () { + called = true; + }, + ), + ); + + await tester.tap(find.byType(CTAButton)); + expect(called, isTrue); + }); + }); +} diff --git a/test/home/widgets/initial_screen_test.dart b/test/home/widgets/initial_screen_test.dart new file mode 100644 index 0000000..58bc45e --- /dev/null +++ b/test/home/widgets/initial_screen_test.dart @@ -0,0 +1,22 @@ +// ignore_for_file: prefer_const_constructors + +import 'package:dash_ai_search/home/home.dart'; +import 'package:dash_ai_search/l10n/l10n.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../../helpers/helpers.dart'; + +void main() { + group('InitialScreen', () { + testWidgets('renders correctly', (tester) async { + await tester.pumpApp( + InitialScreen(), + ); + + final l10n = tester.element(find.byType(InitialScreen)).l10n; + + expect(find.text(l10n.initialScreenTitle), findsOneWidget); + expect(find.byType(CTAButton), findsOneWidget); + }); + }); +} diff --git a/test/home/widgets/logo_test.dart b/test/home/widgets/logo_test.dart new file mode 100644 index 0000000..63c8095 --- /dev/null +++ b/test/home/widgets/logo_test.dart @@ -0,0 +1,24 @@ +// ignore_for_file: prefer_const_constructors + +import 'package:dash_ai_search/home/home.dart'; +import 'package:dash_ai_search/l10n/l10n.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../../helpers/helpers.dart'; + +void main() { + group('Logo', () { + testWidgets('renders correctly', (tester) async { + await tester.pumpApp( + Logo(), + ); + + final l10n = tester.element(find.byType(Logo)).l10n; + + expect(find.text(l10n.vertexAI), findsOneWidget); + expect(find.byType(Image), findsOneWidget); + expect(find.text(l10n.flutter), findsOneWidget); + }); + }); +} From 8da5aeac2b9b38532e235ba07fc9da1483ca932e Mon Sep 17 00:00:00 2001 From: RuiAlonso Date: Wed, 22 Nov 2023 10:07:35 +0100 Subject: [PATCH 4/9] feat: dotted circle --- lib/home/widgets/background.dart | 30 ++++++++++++++++++++++-------- pubspec.lock | 16 ++++++++++++++++ pubspec.yaml | 1 + 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/lib/home/widgets/background.dart b/lib/home/widgets/background.dart index 8264b5f..7543998 100644 --- a/lib/home/widgets/background.dart +++ b/lib/home/widgets/background.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:path_drawing/path_drawing.dart'; class Background extends StatelessWidget { const Background({super.key}); @@ -21,11 +22,11 @@ class Background extends StatelessWidget { child: Circle( offset: Offset(diameter + leftOffset, 0), radius: 255, - borderColor: Color(0xFFBAC4E1), + borderColor: Color(0xFFDDE2F6), child: Circle( offset: Offset(diameter + leftOffset, 0), radius: 185, - borderColor: Color(0xFFBAC4E1), + borderColor: Color(0xFFDDE2F6), dotted: true, ), ), @@ -85,7 +86,8 @@ class CirclePainter extends CustomPainter { ..style = PaintingStyle.fill; _paintBorder = Paint() ..color = borderColor - ..strokeWidth = 1 + ..strokeWidth = 2 + ..strokeCap = StrokeCap.butt ..style = PaintingStyle.stroke; } @@ -106,11 +108,23 @@ class CirclePainter extends CustomPainter { ); if (dotted) { - canvas.drawCircle( - offset, - radius, - _paintBorder, - ); + const dashPattern = [4, 4]; + final s = radius * 2; + + var path = Path() + ..addRRect( + RRect.fromRectAndRadius( + Rect.fromLTWH( + offset.dx - s / 2, + offset.dy / 2 - s / 2, + s, + s, + ), + Radius.circular(s / 2), + ), + ); + path = dashPath(path, dashArray: CircularIntervalList(dashPattern)); + canvas.drawPath(path, _paintBorder); } else { canvas.drawCircle( offset, diff --git a/pubspec.lock b/pubspec.lock index 4d559b1..e6e34b3 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -447,6 +447,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.8.3" + path_drawing: + dependency: "direct main" + description: + name: path_drawing + sha256: bbb1934c0cbb03091af082a6389ca2080345291ef07a5fa6d6e078ba8682f977 + url: "https://pub.dev" + source: hosted + version: "1.0.1" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf + url: "https://pub.dev" + source: hosted + version: "1.0.1" petitparser: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index a531115..36284cf 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,6 +17,7 @@ dependencies: flutter_localizations: sdk: flutter intl: ^0.18.0 + path_drawing: ^1.0.1 dev_dependencies: bloc_test: ^9.1.4 From cf240adc1ddcb4700f948d04955c5db59c40cf3e Mon Sep 17 00:00:00 2001 From: RuiAlonso Date: Wed, 22 Nov 2023 10:25:48 +0100 Subject: [PATCH 5/9] feat: added dash animation --- lib/home/view/home_page.dart | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/lib/home/view/home_page.dart b/lib/home/view/home_page.dart index 0c361a1..24fc131 100644 --- a/lib/home/view/home_page.dart +++ b/lib/home/view/home_page.dart @@ -1,3 +1,4 @@ +import 'package:app_ui/app_ui.dart'; import 'package:dash_ai_search/home/home.dart'; import 'package:flutter/material.dart'; @@ -21,8 +22,40 @@ class HomePage extends StatelessWidget { child: Logo(), ), InitialScreen(), + Positioned( + bottom: 50, + left: 50, + child: DashAnimation(), + ), ], ), ); } } + +class DashAnimation extends StatelessWidget { + @visibleForTesting + const DashAnimation({super.key}); + + static const dashSize = Size(800, 800); + + @override + Widget build(BuildContext context) { + final screenSize = MediaQuery.sizeOf(context); + + return Container( + alignment: Alignment.center, + height: screenSize.height / 3, + width: screenSize.height / 3, + child: const AnimatedSprite( + showLoadingIndicator: false, + sprites: Sprites( + asset: 'dash_animation.png', + size: dashSize, + frames: 34, + stepTime: 0.07, + ), + ), + ); + } +} From 4571f964316aa7965391f024f0369d3e2fb792ca Mon Sep 17 00:00:00 2001 From: RuiAlonso Date: Wed, 22 Nov 2023 10:30:38 +0100 Subject: [PATCH 6/9] feat: cleaned background --- lib/home/widgets/background.dart | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/lib/home/widgets/background.dart b/lib/home/widgets/background.dart index 7543998..a9a7d2c 100644 --- a/lib/home/widgets/background.dart +++ b/lib/home/widgets/background.dart @@ -7,8 +7,10 @@ class Background extends StatelessWidget { @override Widget build(BuildContext context) { const leftOffset = -50.0; - const radius = 303.0; - const diameter = radius * 2; + const baseRadius = 303.0; + const baseMediumRadius = 255.0; + const baseSmallRadius = 185.0; + const horizontalOffset = baseRadius * 2; return const SingleChildScrollView( scrollDirection: Axis.horizontal, @@ -18,24 +20,24 @@ class Background extends StatelessWidget { offset: Offset(leftOffset, 0), ), Circle( - offset: Offset(diameter + leftOffset, 0), + offset: Offset(horizontalOffset + leftOffset, 0), child: Circle( - offset: Offset(diameter + leftOffset, 0), - radius: 255, + offset: Offset(horizontalOffset + leftOffset, 0), + radius: baseMediumRadius, borderColor: Color(0xFFDDE2F6), child: Circle( - offset: Offset(diameter + leftOffset, 0), - radius: 185, + offset: Offset(horizontalOffset + leftOffset, 0), + radius: baseSmallRadius, borderColor: Color(0xFFDDE2F6), dotted: true, ), ), ), Circle( - offset: Offset(diameter * 2 + leftOffset, 0), + offset: Offset(horizontalOffset * 2 + leftOffset, 0), ), Circle( - offset: Offset(diameter * 3 + leftOffset, 0), + offset: Offset(horizontalOffset * 3 + leftOffset, 0), ), ], ), From 329766cf0535d4364b0f3519922e3e7210903317 Mon Sep 17 00:00:00 2001 From: RuiAlonso Date: Wed, 22 Nov 2023 12:31:19 +0100 Subject: [PATCH 7/9] fix: applied changes from comments --- lib/home/view/home_page.dart | 2 +- lib/home/widgets/cta_button.dart | 44 ------------- lib/home/widgets/logo.dart | 4 +- ...{initial_screen.dart => welcome_view.dart} | 9 ++- lib/home/widgets/widgets.dart | 3 +- .../app_ui/assets}/icons/arrow_forward.png | Bin .../app_ui/assets}/icons/asterisk.png | Bin packages/app_ui/lib/app_ui.dart | 6 ++ .../app_ui/lib/src/generated}/assets.gen.dart | 6 +- .../app_ui/lib/src/widgets/cta_button.dart | 59 ++++++++++++++++++ packages/app_ui/lib/src/widgets/widgets.dart | 1 + packages/app_ui/pubspec.yaml | 14 +++++ .../app_ui/test/src/analysis_options.yaml | 4 ++ .../test/src/widgets/cta_button_test.dart | 46 ++++++++++++++ pubspec.yaml | 1 - test/analysis_options.yaml | 4 ++ test/app/view/app_test.dart | 4 +- test/home/view/home_page_test.dart | 4 +- test/home/widgets/background_test.dart | 2 - test/home/widgets/cta_button_test.dart | 40 ------------ test/home/widgets/logo_test.dart | 2 - ...creen_test.dart => welcome_view_test.dart} | 9 ++- 22 files changed, 152 insertions(+), 112 deletions(-) delete mode 100644 lib/home/widgets/cta_button.dart rename lib/home/widgets/{initial_screen.dart => welcome_view.dart} (76%) rename {assets => packages/app_ui/assets}/icons/arrow_forward.png (100%) rename {assets => packages/app_ui/assets}/icons/asterisk.png (100%) rename {lib/gen => packages/app_ui/lib/src/generated}/assets.gen.dart (95%) create mode 100644 packages/app_ui/lib/src/widgets/cta_button.dart create mode 100644 packages/app_ui/test/src/analysis_options.yaml create mode 100644 packages/app_ui/test/src/widgets/cta_button_test.dart create mode 100644 test/analysis_options.yaml delete mode 100644 test/home/widgets/cta_button_test.dart rename test/home/widgets/{initial_screen_test.dart => welcome_view_test.dart} (71%) diff --git a/lib/home/view/home_page.dart b/lib/home/view/home_page.dart index 24fc131..f516626 100644 --- a/lib/home/view/home_page.dart +++ b/lib/home/view/home_page.dart @@ -21,7 +21,7 @@ class HomePage extends StatelessWidget { left: 48, child: Logo(), ), - InitialScreen(), + WelcomeView(), Positioned( bottom: 50, left: 50, diff --git a/lib/home/widgets/cta_button.dart b/lib/home/widgets/cta_button.dart deleted file mode 100644 index 085d091..0000000 --- a/lib/home/widgets/cta_button.dart +++ /dev/null @@ -1,44 +0,0 @@ -import 'package:flutter/material.dart'; - -class CTAButton extends StatelessWidget { - const CTAButton({ - required this.icon, - required this.label, - this.onPressed, - super.key, - }); - - final Image icon; - final String label; - final VoidCallback? onPressed; - - @override - Widget build(BuildContext context) { - return TextButton.icon( - icon: icon, - label: Text( - label, - textAlign: TextAlign.center, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.w500, - color: Colors.white, - ), - ), - style: const ButtonStyle( - backgroundColor: MaterialStatePropertyAll( - Color(0xFF0273E6), - ), - padding: MaterialStatePropertyAll( - EdgeInsets.only( - left: 24, - top: 20, - bottom: 20, - right: 32, - ), - ), - ), - onPressed: onPressed, - ); - } -} diff --git a/lib/home/widgets/logo.dart b/lib/home/widgets/logo.dart index 6f265ad..47ccab7 100644 --- a/lib/home/widgets/logo.dart +++ b/lib/home/widgets/logo.dart @@ -1,4 +1,4 @@ -import 'package:dash_ai_search/gen/assets.gen.dart'; +import 'package:app_ui/app_ui.dart'; import 'package:dash_ai_search/l10n/l10n.dart'; import 'package:flutter/material.dart'; @@ -20,7 +20,7 @@ class Logo extends StatelessWidget { ), ), const SizedBox(width: 4), - Assets.icons.asterisk.image(), + VertexIcons.asterisk.image(), const SizedBox(width: 4), Text( l10n.flutter, diff --git a/lib/home/widgets/initial_screen.dart b/lib/home/widgets/welcome_view.dart similarity index 76% rename from lib/home/widgets/initial_screen.dart rename to lib/home/widgets/welcome_view.dart index 98a6280..0651a9c 100644 --- a/lib/home/widgets/initial_screen.dart +++ b/lib/home/widgets/welcome_view.dart @@ -1,10 +1,9 @@ -import 'package:dash_ai_search/gen/assets.gen.dart'; -import 'package:dash_ai_search/home/home.dart'; +import 'package:app_ui/app_ui.dart'; import 'package:dash_ai_search/l10n/l10n.dart'; import 'package:flutter/material.dart'; -class InitialScreen extends StatelessWidget { - const InitialScreen({super.key}); +class WelcomeView extends StatelessWidget { + const WelcomeView({super.key}); @override Widget build(BuildContext context) { @@ -26,7 +25,7 @@ class InitialScreen extends StatelessWidget { ), const SizedBox(height: 40), CTAButton( - icon: Assets.icons.arrowForward.image(), + icon: VertexIcons.arrowForward.image(), label: l10n.startAsking, ), ], diff --git a/lib/home/widgets/widgets.dart b/lib/home/widgets/widgets.dart index 1244f80..47cbead 100644 --- a/lib/home/widgets/widgets.dart +++ b/lib/home/widgets/widgets.dart @@ -1,4 +1,3 @@ export 'background.dart'; -export 'cta_button.dart'; -export 'initial_screen.dart'; export 'logo.dart'; +export 'welcome_view.dart'; diff --git a/assets/icons/arrow_forward.png b/packages/app_ui/assets/icons/arrow_forward.png similarity index 100% rename from assets/icons/arrow_forward.png rename to packages/app_ui/assets/icons/arrow_forward.png diff --git a/assets/icons/asterisk.png b/packages/app_ui/assets/icons/asterisk.png similarity index 100% rename from assets/icons/asterisk.png rename to packages/app_ui/assets/icons/asterisk.png diff --git a/packages/app_ui/lib/app_ui.dart b/packages/app_ui/lib/app_ui.dart index 9ef06cd..71f391c 100644 --- a/packages/app_ui/lib/app_ui.dart +++ b/packages/app_ui/lib/app_ui.dart @@ -1 +1,7 @@ +import 'package:app_ui/src/generated/assets.gen.dart'; + export 'src/widgets/widgets.dart'; + +/// Global reference to actual app_ui icons. +// ignore: constant_identifier_names +const VertexIcons = Assets.icons; diff --git a/lib/gen/assets.gen.dart b/packages/app_ui/lib/src/generated/assets.gen.dart similarity index 95% rename from lib/gen/assets.gen.dart rename to packages/app_ui/lib/src/generated/assets.gen.dart index 42f4e15..b05f67f 100644 --- a/lib/gen/assets.gen.dart +++ b/packages/app_ui/lib/src/generated/assets.gen.dart @@ -55,7 +55,7 @@ class AssetGenImage { bool matchTextDirection = false, bool gaplessPlayback = false, bool isAntiAlias = false, - String? package, + String? package = 'app_ui', FilterQuality filterQuality = FilterQuality.low, int? cacheWidth, int? cacheHeight, @@ -90,7 +90,7 @@ class AssetGenImage { ImageProvider provider({ AssetBundle? bundle, - String? package, + String? package = 'app_ui', }) { return AssetImage( _assetName, @@ -101,5 +101,5 @@ class AssetGenImage { String get path => _assetName; - String get keyName => _assetName; + String get keyName => 'packages/app_ui/$_assetName'; } diff --git a/packages/app_ui/lib/src/widgets/cta_button.dart b/packages/app_ui/lib/src/widgets/cta_button.dart new file mode 100644 index 0000000..79f3b9c --- /dev/null +++ b/packages/app_ui/lib/src/widgets/cta_button.dart @@ -0,0 +1,59 @@ +import 'package:flutter/material.dart'; + +/// {@template cta_button} +/// A button that displays an image on the left side and a text on the right +/// side. +/// {@endtemplate} +class CTAButton extends StatelessWidget { + /// {@macro cta_button} + const CTAButton({ + required this.label, + this.icon, + this.onPressed, + super.key, + }); + + /// The image that will be displayed on the left side of the button. + final Image? icon; + + /// The text that will be displayed on the right side of the button. + final String label; + + /// The callback that will be called when the button is tapped. + final VoidCallback? onPressed; + + @override + Widget build(BuildContext context) { + return ElevatedButton( + onPressed: onPressed, + style: const ButtonStyle( + backgroundColor: MaterialStatePropertyAll( + Color(0xFF0273E6), + ), + padding: MaterialStatePropertyAll( + EdgeInsets.only( + left: 24, + top: 20, + bottom: 20, + right: 32, + ), + ), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + if (icon != null) icon!, + Text( + label, + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + color: Colors.white, + ), + ), + ], + ), + ); + } +} diff --git a/packages/app_ui/lib/src/widgets/widgets.dart b/packages/app_ui/lib/src/widgets/widgets.dart index 08e3705..036ed92 100644 --- a/packages/app_ui/lib/src/widgets/widgets.dart +++ b/packages/app_ui/lib/src/widgets/widgets.dart @@ -1,3 +1,4 @@ export 'animated_sprite.dart'; export 'app_animated_cross_fade.dart'; export 'app_circular_progress_indicator.dart'; +export 'cta_button.dart'; diff --git a/packages/app_ui/pubspec.yaml b/packages/app_ui/pubspec.yaml index e7109d2..f2802c4 100644 --- a/packages/app_ui/pubspec.yaml +++ b/packages/app_ui/pubspec.yaml @@ -13,7 +13,21 @@ dependencies: sdk: flutter dev_dependencies: + build_runner: ^2.4.6 flutter_test: sdk: flutter + flutter_gen_runner: ^5.3.2 mocktail: ^1.0.0 very_good_analysis: ^5.1.0 + +flutter_gen: + assets: + outputs: + package_parameter_enabled: true + output: lib/src/generated/ + line_length: 80 + +flutter: + uses-material-design: true + assets: + - assets/icons/ diff --git a/packages/app_ui/test/src/analysis_options.yaml b/packages/app_ui/test/src/analysis_options.yaml new file mode 100644 index 0000000..453605c --- /dev/null +++ b/packages/app_ui/test/src/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:very_good_analysis/analysis_options.5.1.0.yaml +linter: + rules: + prefer_const_constructors: false \ No newline at end of file diff --git a/packages/app_ui/test/src/widgets/cta_button_test.dart b/packages/app_ui/test/src/widgets/cta_button_test.dart new file mode 100644 index 0000000..9b86344 --- /dev/null +++ b/packages/app_ui/test/src/widgets/cta_button_test.dart @@ -0,0 +1,46 @@ +import 'package:app_ui/app_ui.dart'; +import 'package:app_ui/src/generated/assets.gen.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('CTAButton', () { + Widget bootstrap({ + required Widget child, + }) { + return MaterialApp(home: child); + } + + testWidgets('renders correctly', (tester) async { + await tester.pumpWidget( + bootstrap( + child: CTAButton( + icon: Assets.icons.arrowForward.image(), + label: 'label', + ), + ), + ); + + expect(find.text('label'), findsOneWidget); + }); + + testWidgets('calls onPressed when tap', (tester) async { + var called = false; + + await tester.pumpWidget( + bootstrap( + child: CTAButton( + icon: Assets.icons.arrowForward.image(), + label: 'label', + onPressed: () { + called = true; + }, + ), + ), + ); + + await tester.tap(find.byType(CTAButton)); + expect(called, isTrue); + }); + }); +} diff --git a/pubspec.yaml b/pubspec.yaml index 23332b6..ed40e79 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -39,4 +39,3 @@ flutter: generate: true assets: - assets/animations/ - - assets/icons/ diff --git a/test/analysis_options.yaml b/test/analysis_options.yaml new file mode 100644 index 0000000..453605c --- /dev/null +++ b/test/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:very_good_analysis/analysis_options.5.1.0.yaml +linter: + rules: + prefer_const_constructors: false \ No newline at end of file diff --git a/test/app/view/app_test.dart b/test/app/view/app_test.dart index b4e958b..5fcad3e 100644 --- a/test/app/view/app_test.dart +++ b/test/app/view/app_test.dart @@ -1,6 +1,6 @@ import 'package:api_client/api_client.dart'; import 'package:dash_ai_search/app/app.dart'; -import 'package:dash_ai_search/home/view/home_page.dart'; +import 'package:dash_ai_search/home/home.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -14,7 +14,7 @@ void main() { apiClient = _MockApiClient(); }); - testWidgets('renders correctly', (tester) async { + testWidgets('renders HomePage', (tester) async { await tester.pumpWidget( App( apiClient: apiClient, diff --git a/test/home/view/home_page_test.dart b/test/home/view/home_page_test.dart index 271287a..d51ff18 100644 --- a/test/home/view/home_page_test.dart +++ b/test/home/view/home_page_test.dart @@ -1,5 +1,3 @@ -// ignore_for_file: prefer_const_constructors - import 'package:dash_ai_search/home/home.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -14,7 +12,7 @@ void main() { expect(find.byType(Background), findsOneWidget); expect(find.byType(Logo), findsOneWidget); - expect(find.byType(InitialScreen), findsOneWidget); + expect(find.byType(WelcomeView), findsOneWidget); }); }); } diff --git a/test/home/widgets/background_test.dart b/test/home/widgets/background_test.dart index 3957a3f..e2d890f 100644 --- a/test/home/widgets/background_test.dart +++ b/test/home/widgets/background_test.dart @@ -1,5 +1,3 @@ -// ignore_for_file: prefer_const_constructors - import 'package:dash_ai_search/home/home.dart'; import 'package:flutter_test/flutter_test.dart'; diff --git a/test/home/widgets/cta_button_test.dart b/test/home/widgets/cta_button_test.dart deleted file mode 100644 index 5a944cb..0000000 --- a/test/home/widgets/cta_button_test.dart +++ /dev/null @@ -1,40 +0,0 @@ -// ignore_for_file: prefer_const_constructors - -import 'package:dash_ai_search/gen/assets.gen.dart'; -import 'package:dash_ai_search/home/home.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import '../../helpers/helpers.dart'; - -void main() { - group('CTAButton', () { - testWidgets('renders correctly', (tester) async { - await tester.pumpApp( - CTAButton( - icon: Assets.icons.arrowForward.image(), - label: 'label', - onPressed: () {}, - ), - ); - - expect(find.text('label'), findsOneWidget); - }); - - testWidgets('calls onPressed when tap', (tester) async { - var called = false; - - await tester.pumpApp( - CTAButton( - icon: Assets.icons.arrowForward.image(), - label: 'label', - onPressed: () { - called = true; - }, - ), - ); - - await tester.tap(find.byType(CTAButton)); - expect(called, isTrue); - }); - }); -} diff --git a/test/home/widgets/logo_test.dart b/test/home/widgets/logo_test.dart index 63c8095..19b3df9 100644 --- a/test/home/widgets/logo_test.dart +++ b/test/home/widgets/logo_test.dart @@ -1,5 +1,3 @@ -// ignore_for_file: prefer_const_constructors - import 'package:dash_ai_search/home/home.dart'; import 'package:dash_ai_search/l10n/l10n.dart'; import 'package:flutter/material.dart'; diff --git a/test/home/widgets/initial_screen_test.dart b/test/home/widgets/welcome_view_test.dart similarity index 71% rename from test/home/widgets/initial_screen_test.dart rename to test/home/widgets/welcome_view_test.dart index 58bc45e..562d9c5 100644 --- a/test/home/widgets/initial_screen_test.dart +++ b/test/home/widgets/welcome_view_test.dart @@ -1,5 +1,4 @@ -// ignore_for_file: prefer_const_constructors - +import 'package:app_ui/app_ui.dart'; import 'package:dash_ai_search/home/home.dart'; import 'package:dash_ai_search/l10n/l10n.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -7,13 +6,13 @@ import 'package:flutter_test/flutter_test.dart'; import '../../helpers/helpers.dart'; void main() { - group('InitialScreen', () { + group('WelcomeView', () { testWidgets('renders correctly', (tester) async { await tester.pumpApp( - InitialScreen(), + WelcomeView(), ); - final l10n = tester.element(find.byType(InitialScreen)).l10n; + final l10n = tester.element(find.byType(WelcomeView)).l10n; expect(find.text(l10n.initialScreenTitle), findsOneWidget); expect(find.byType(CTAButton), findsOneWidget); From bb43f55589d3909c4ad4976c0109cdc5c67ca0d3 Mon Sep 17 00:00:00 2001 From: RuiAlonso Date: Wed, 22 Nov 2023 12:35:56 +0100 Subject: [PATCH 8/9] test: covered ignored method --- lib/home/widgets/background.dart | 2 -- test/home/widgets/background_test.dart | 11 +++++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/home/widgets/background.dart b/lib/home/widgets/background.dart index a9a7d2c..e224545 100644 --- a/lib/home/widgets/background.dart +++ b/lib/home/widgets/background.dart @@ -136,8 +136,6 @@ class CirclePainter extends CustomPainter { } } - // coverage:ignore-start @override bool shouldRepaint(CustomPainter oldDelegate) => false; - // coverage:ignore-end } diff --git a/test/home/widgets/background_test.dart b/test/home/widgets/background_test.dart index e2d890f..cdc446f 100644 --- a/test/home/widgets/background_test.dart +++ b/test/home/widgets/background_test.dart @@ -1,4 +1,5 @@ import 'package:dash_ai_search/home/home.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import '../../helpers/helpers.dart'; @@ -12,5 +13,15 @@ void main() { expect(find.byType(Circle), findsNWidgets(6)); }); + + test('verifies should not repaint', () async { + final circlePainter = CirclePainter( + offset: Offset.zero, + radius: 10, + borderColor: Colors.white, + dotted: false, + ); + expect(circlePainter.shouldRepaint(circlePainter), false); + }); }); } From 9510db6ff950dd659825030846598fe64744a4c4 Mon Sep 17 00:00:00 2001 From: RuiAlonso Date: Wed, 22 Nov 2023 13:31:07 +0100 Subject: [PATCH 9/9] chore" fixed comments --- lib/home/widgets/logo.dart | 2 +- lib/home/widgets/welcome_view.dart | 2 +- packages/app_ui/lib/app_ui.dart | 3 +- packages/app_ui/test/src/helpers/helpers.dart | 1 + .../app_ui/test/src/helpers/pump_app.dart | 12 +++++++ .../test/src/widgets/cta_button_test.dart | 35 +++++++------------ 6 files changed, 29 insertions(+), 26 deletions(-) create mode 100644 packages/app_ui/test/src/helpers/helpers.dart create mode 100644 packages/app_ui/test/src/helpers/pump_app.dart diff --git a/lib/home/widgets/logo.dart b/lib/home/widgets/logo.dart index 47ccab7..c72a584 100644 --- a/lib/home/widgets/logo.dart +++ b/lib/home/widgets/logo.dart @@ -20,7 +20,7 @@ class Logo extends StatelessWidget { ), ), const SizedBox(width: 4), - VertexIcons.asterisk.image(), + vertexIcons.asterisk.image(), const SizedBox(width: 4), Text( l10n.flutter, diff --git a/lib/home/widgets/welcome_view.dart b/lib/home/widgets/welcome_view.dart index 0651a9c..8633644 100644 --- a/lib/home/widgets/welcome_view.dart +++ b/lib/home/widgets/welcome_view.dart @@ -25,7 +25,7 @@ class WelcomeView extends StatelessWidget { ), const SizedBox(height: 40), CTAButton( - icon: VertexIcons.arrowForward.image(), + icon: vertexIcons.arrowForward.image(), label: l10n.startAsking, ), ], diff --git a/packages/app_ui/lib/app_ui.dart b/packages/app_ui/lib/app_ui.dart index 71f391c..fbff115 100644 --- a/packages/app_ui/lib/app_ui.dart +++ b/packages/app_ui/lib/app_ui.dart @@ -3,5 +3,4 @@ import 'package:app_ui/src/generated/assets.gen.dart'; export 'src/widgets/widgets.dart'; /// Global reference to actual app_ui icons. -// ignore: constant_identifier_names -const VertexIcons = Assets.icons; +const vertexIcons = Assets.icons; diff --git a/packages/app_ui/test/src/helpers/helpers.dart b/packages/app_ui/test/src/helpers/helpers.dart new file mode 100644 index 0000000..b15fe65 --- /dev/null +++ b/packages/app_ui/test/src/helpers/helpers.dart @@ -0,0 +1 @@ +export 'pump_app.dart'; diff --git a/packages/app_ui/test/src/helpers/pump_app.dart b/packages/app_ui/test/src/helpers/pump_app.dart new file mode 100644 index 0000000..461f44a --- /dev/null +++ b/packages/app_ui/test/src/helpers/pump_app.dart @@ -0,0 +1,12 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +extension PumpApp on WidgetTester { + Future pumpApp(Widget widget) { + return pumpWidget( + MaterialApp( + home: widget, + ), + ); + } +} diff --git a/packages/app_ui/test/src/widgets/cta_button_test.dart b/packages/app_ui/test/src/widgets/cta_button_test.dart index 9b86344..c529ada 100644 --- a/packages/app_ui/test/src/widgets/cta_button_test.dart +++ b/packages/app_ui/test/src/widgets/cta_button_test.dart @@ -1,23 +1,16 @@ import 'package:app_ui/app_ui.dart'; import 'package:app_ui/src/generated/assets.gen.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import '../helpers/helpers.dart'; + void main() { group('CTAButton', () { - Widget bootstrap({ - required Widget child, - }) { - return MaterialApp(home: child); - } - testWidgets('renders correctly', (tester) async { - await tester.pumpWidget( - bootstrap( - child: CTAButton( - icon: Assets.icons.arrowForward.image(), - label: 'label', - ), + await tester.pumpApp( + CTAButton( + icon: Assets.icons.arrowForward.image(), + label: 'label', ), ); @@ -27,15 +20,13 @@ void main() { testWidgets('calls onPressed when tap', (tester) async { var called = false; - await tester.pumpWidget( - bootstrap( - child: CTAButton( - icon: Assets.icons.arrowForward.image(), - label: 'label', - onPressed: () { - called = true; - }, - ), + await tester.pumpApp( + CTAButton( + icon: Assets.icons.arrowForward.image(), + label: 'label', + onPressed: () { + called = true; + }, ), );