This commit is contained in:
Felipe
2024-03-13 13:59:33 -05:00
parent 312cc3d863
commit a25bc6a987
26 changed files with 684 additions and 60 deletions
+10 -4
View File
@@ -2,6 +2,7 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:prosappco/blocs/my_user_bloc/my_user_bloc.dart';
import 'package:prosappco/screens/city/city_screen.dart';
import 'package:prosappco/screens/profile/profile_screen.dart';
class GeneralDrawerHeader extends StatelessWidget {
@@ -20,15 +21,20 @@ class GeneralDrawerHeader extends StatelessWidget {
CupertinoPageRoute(
builder: (BuildContext context) {
return const ProfileScreen();
// return const CityScreen();
},
),
);
},
title: Text(user.name ?? '',style: const TextStyle(fontWeight: FontWeight.bold)),
subtitle: Text(user.drawerLabel,style: const TextStyle(fontSize: 12)),
title: Text(user.name ?? '',
style: const TextStyle(fontWeight: FontWeight.bold)),
subtitle:
Text(user.drawerLabel, style: const TextStyle(fontSize: 12)),
leading: pictureWidget(user.picture, context),
trailing: const Icon(Icons.keyboard_arrow_right, color: Colors.black),
contentPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15),
trailing:
const Icon(Icons.keyboard_arrow_right, color: Colors.black),
contentPadding:
const EdgeInsets.symmetric(vertical: 10, horizontal: 15),
);
} else if (state.status == MyUserStatus.failure) {
return const Text('Error obteniendo datos del usuario');
@@ -8,14 +8,17 @@ import 'package:prosappco/blocs/setting_bloc/setting_bloc.dart';
import 'package:prosappco/blocs/sign_up_bloc/sign_up_bloc.dart';
import 'package:prosappco/blocs/sing_in_bloc/sign_in_bloc.dart';
import 'package:user_repository/user_repository.dart';
import 'package:city_repository/city_repository.dart';
class UserDI {
class AppDI {
void register() {
final injector = Injector.appInstance;
injector.registerSingleton<UserRepository>(
(() => FirebaseUserRepository(FirebaseAuth.instance)));
injector.registerSingleton<CityRepository>(() => FirebaseCityRepository());
injector.registerSingleton<AuthenticationBloc>((() =>
AuthenticationBloc(myUserRepository: injector.get<UserRepository>())));
+2 -2
View File
@@ -173,7 +173,7 @@ import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:prosappco/dependency_user/user_di.dart';
import 'package:prosappco/dependency/app_di.dart';
import 'app.dart';
import 'simple_bloc_observer.dart';
@@ -182,6 +182,6 @@ void main() async {
await Firebase.initializeApp();
Bloc.observer = SimpleBlocObserver();
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
UserDI().register();
AppDI().register();
runApp(const MainApp());
}
+165
View File
@@ -0,0 +1,165 @@
import 'package:city_repository/city_repository.dart';
import 'package:flutter/material.dart';
import 'package:injector/injector.dart';
import 'package:intl_phone_field/helpers.dart';
import 'package:prosappco/src/components/pop_appbar.dart';
import 'package:shimmer/shimmer.dart';
class CityScreen extends StatefulWidget {
const CityScreen({Key? key}) : super(key: key);
@override
State<CityScreen> createState() => _CityScreenState();
}
class _CityScreenState extends State<CityScreen> {
final _searchController = TextEditingController();
final cityRepository = Injector.appInstance.get<CityRepository>();
List<CityUi>? _cities;
List<CityUi>? _filteredCities;
bool _isLoading = true;
@override
void initState() {
super.initState();
_loadCities();
}
void _loadCities() {
cityRepository.getCities().then((List<CityUi> element) {
setState(() {
_cities = element;
_filteredCities = _cities;
_isLoading = false;
});
});
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: PopAppbar(
onPressed: () {
Navigator.pop(context);
},
label: 'Ciudad',
),
body: Column(
children: [
Padding(
padding: const EdgeInsets.only(left: 15, right: 15, bottom: 15),
child: TextField(
controller: _searchController,
onChanged: (value) {
_filterCities(value);
},
decoration: const InputDecoration(
hintText: 'Busca una ciudad',
prefixIcon: Icon(Icons.search),
),
),
),
_isLoading
? _buildShimmerEffect()
: Expanded(
child: _filteredCities != null && _filteredCities!.isNotEmpty
? ListView.builder(
itemCount: _filteredCities!.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(
_filteredCities![index].cityName,
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black87,
),
),
subtitle: Text(
"${_filteredCities![index].stateOfCity}, ${_filteredCities![index].countryOfCity}",
style: const TextStyle(color: Colors.black54),
),
onTap: () {
// Handle city selection
},
);
},
)
: const Center(
child: Text('No se encontraron ciudades.'),
),
),
],
),
),
);
}
void _filterCities(String query) {
if (_cities != null) {
setState(() {
_filteredCities = _cities!
.where((city) => removeDiacritics(city.cityName.toLowerCase())
.contains(removeDiacritics(query.toLowerCase())))
.toList();
});
}
}
Widget _buildShimmerEffect() {
return Expanded(
child: Shimmer.fromColors(
baseColor: Colors.grey[300]!,
highlightColor: Colors.grey[100]!,
child: ListView.builder(
itemCount: 8,
itemBuilder: (_, __) => const ListTileShimmer(),
),
),
);
}
}
class ListTileShimmer extends StatelessWidget {
const ListTileShimmer({super.key});
@override
Widget build(BuildContext context) {
return ListTile(
title: Row(
children: [
Container(
width: MediaQuery.of(context).size.width * 0.8,
height: 18.0,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
),
),
],
),
subtitle: Row(
children: [
Container(
width: MediaQuery.of(context).size.width * 0.3,
height: 15.0,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
),
),
const SizedBox(width: 5),
Container(
width: MediaQuery.of(context).size.width * 0.3,
height: 15.0,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
),
)
],
),
);
}
}
+38
View File
@@ -10,6 +10,7 @@ import 'package:prosappco/blocs/my_user_bloc/my_user_bloc.dart';
import 'package:prosappco/blocs/profile_bloc/profile_bloc.dart';
import 'package:prosappco/components/birthday_picker.dart';
import 'package:prosappco/components/gender_dropdown.dart';
import 'package:prosappco/screens/city/city_screen.dart';
import 'package:prosappco/screens/profile/components/profile_item.dart';
import 'package:prosappco/screens/profile/profile_register_email_screen.dart';
import 'package:prosappco/screens/profile/profile_register_phone_screen.dart';
@@ -128,6 +129,43 @@ class _ProfileScreenState extends State<ProfileScreen> {
return null;
},
),
const SizedBox(height: 20.0),
TextFormField(
// controller: _nameController,
readOnly: true,
onTap: () {
Navigator.push(
context,
CupertinoPageRoute(
builder: (BuildContext context) {
return const CityScreen();
},
),
);
},
decoration: const InputDecoration(
labelText: 'Ciudad',
prefixIcon: Icon(Icons.near_me_rounded),
hintText: 'Elige tu ciudad',
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(10.0),
)),
errorBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.red),
),
focusedErrorBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.red, width: 2.0),
),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Por favor, ingrese su nombre';
}
return null;
},
),
_birthdayController.text.isEmpty &&
_genderController.text.isEmpty
? Column(
@@ -0,0 +1,6 @@
library city_repository;
export 'src/models/models.dart';
export 'src/entities/entities.dart';
export 'src/repositories/city_repo.dart';
export 'src/repositories/firebase_city_repository.dart';
@@ -1,5 +1,5 @@
import 'package:equatable/equatable.dart';
import 'package:user_repository/user_repository.dart';
import 'package:city_repository/city_repository.dart';
class CountryEntity extends Equatable {
final String name;
@@ -13,14 +13,14 @@ class CountryEntity extends Equatable {
Map<String, Object?> toDocument() {
return {
'name': name,
'regions': regions,
'states': regions,
};
}
static CountryEntity fromDocument(Map<String, dynamic> doc) {
return CountryEntity(
name: doc['name'] as String,
regions: (doc['regions'] as List)
regions: (doc['states'] as List)
.map((region) => RegionEntity.fromDocument(region))
.toList(),
);
@@ -0,0 +1,3 @@
export '/src/entities/country_entity.dart';
export '/src/entities/region_entity.dart';
export '/src/entities/city_entity.dart';
@@ -1,5 +1,5 @@
import 'package:equatable/equatable.dart';
import 'package:user_repository/user_repository.dart';
import 'package:city_repository/city_repository.dart';
class RegionEntity extends Equatable {
final String name;
@@ -1,6 +1,5 @@
import 'package:equatable/equatable.dart';
import '../entities/entities.dart';
import 'package:city_repository/city_repository.dart';
class City extends Equatable {
final String name;
@@ -0,0 +1,19 @@
import 'package:equatable/equatable.dart';
class CityUi extends Equatable {
final String cityName;
final String coordsOfCity;
final String stateOfCity;
final String countryOfCity;
const CityUi({
required this.cityName,
required this.coordsOfCity,
required this.stateOfCity,
required this.countryOfCity,
});
@override
List<Object?> get props =>
[cityName, coordsOfCity, stateOfCity, countryOfCity];
}
@@ -1,5 +1,5 @@
import 'package:equatable/equatable.dart';
import 'package:user_repository/user_repository.dart';
import 'package:city_repository/city_repository.dart';
class Country extends Equatable {
final String name;
@@ -0,0 +1,4 @@
export 'country.dart';
export 'region.dart';
export 'city.dart';
export 'city_ui.dart';
@@ -1,5 +1,5 @@
import 'package:equatable/equatable.dart';
import 'package:user_repository/user_repository.dart';
import 'package:city_repository/city_repository.dart';
class Region extends Equatable {
final String name;
@@ -0,0 +1,6 @@
import 'package:city_repository/city_repository.dart';
import 'package:city_repository/src/models/city_ui.dart';
abstract class CityRepository {
Future<List<CityUi>> getCities();
}
@@ -0,0 +1,44 @@
import 'dart:developer';
import 'package:city_repository/city_repository.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class FirebaseCityRepository implements CityRepository {
final citiesCollection =
FirebaseFirestore.instance.collection('countries v2');
List<CityUi>? _cities;
@override
Future<List<CityUi>> getCities() async {
if (_cities != null) {
return _cities!;
}
final List<CityUi> cities = [];
try {
final doc = await citiesCollection.doc("Colombia").get();
final data = doc.data();
final country = CountryEntity.fromDocument(data as Map<String, dynamic>);
for (var region in country.regions) {
for (var city in region.cities) {
cities.add(CityUi(
cityName: city.name,
coordsOfCity: city.coords,
stateOfCity: region.name,
countryOfCity: country.name));
}
}
} catch (e) {
log(e.toString());
rethrow;
}
_cities = cities;
return cities;
}
}
+338
View File
@@ -0,0 +1,338 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
_flutterfire_internals:
dependency: transitive
description:
name: _flutterfire_internals
sha256: "4eec93681221723a686ad580c2e7d960e1017cf1a4e0a263c2573c2c6b0bf5cd"
url: "https://pub.dev"
source: hosted
version: "1.3.25"
async:
dependency: transitive
description:
name: async
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
url: "https://pub.dev"
source: hosted
version: "2.11.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
characters:
dependency: transitive
description:
name: characters
sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
url: "https://pub.dev"
source: hosted
version: "1.3.0"
clock:
dependency: transitive
description:
name: clock
sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
url: "https://pub.dev"
source: hosted
version: "1.1.1"
cloud_firestore:
dependency: "direct main"
description:
name: cloud_firestore
sha256: "31cfa4d65d6e9ea837234fffe121304034c30c9214c06207b4a35867e3757900"
url: "https://pub.dev"
source: hosted
version: "4.15.8"
cloud_firestore_platform_interface:
dependency: transitive
description:
name: cloud_firestore_platform_interface
sha256: a0097a26569b015faf8142e159e855241609ea9a1738b5fd1c40bfe8411b41a0
url: "https://pub.dev"
source: hosted
version: "6.1.9"
cloud_firestore_web:
dependency: transitive
description:
name: cloud_firestore_web
sha256: ed680ece29a5750985119c09cdc276b460c3a2fa80e8c12f9b7241f6b4a7ca16
url: "https://pub.dev"
source: hosted
version: "3.10.8"
collection:
dependency: transitive
description:
name: collection
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
url: "https://pub.dev"
source: hosted
version: "1.18.0"
equatable:
dependency: "direct main"
description:
name: equatable
sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2
url: "https://pub.dev"
source: hosted
version: "2.0.5"
fake_async:
dependency: transitive
description:
name: fake_async
sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
url: "https://pub.dev"
source: hosted
version: "1.3.1"
firebase_auth:
dependency: "direct main"
description:
name: firebase_auth
sha256: "17b841e1b000c3441b8ffceca88f468e078d0443db9643e77541bdfb7a3fd16b"
url: "https://pub.dev"
source: hosted
version: "4.17.8"
firebase_auth_platform_interface:
dependency: transitive
description:
name: firebase_auth_platform_interface
sha256: f294ceef40409a36c819a14280ca864fe487b44033e5276443377c66cb448310
url: "https://pub.dev"
source: hosted
version: "7.1.8"
firebase_auth_web:
dependency: transitive
description:
name: firebase_auth_web
sha256: "1f231da900fe7ff9f2974f8adcbdb3363c410c24725978afa5dc33e1e7e62e06"
url: "https://pub.dev"
source: hosted
version: "5.9.8"
firebase_core:
dependency: "direct main"
description:
name: firebase_core
sha256: "53316975310c8af75a96e365f9fccb67d1c544ef0acdbf0d88bbe30eedd1c4f9"
url: "https://pub.dev"
source: hosted
version: "2.27.0"
firebase_core_platform_interface:
dependency: transitive
description:
name: firebase_core_platform_interface
sha256: c437ae5d17e6b5cc7981cf6fd458a5db4d12979905f9aafd1fea930428a9fe63
url: "https://pub.dev"
source: hosted
version: "5.0.0"
firebase_core_web:
dependency: transitive
description:
name: firebase_core_web
sha256: c8e1d59385eee98de63c92f961d2a7062c5d9a65e7f45bdc7f1b0b205aab2492
url: "https://pub.dev"
source: hosted
version: "2.11.5"
firebase_storage:
dependency: "direct main"
description:
name: firebase_storage
sha256: ce1b0efe8dc111058c5f079b2f2ce84906d030d0fd2eef70c42ca1253c67039a
url: "https://pub.dev"
source: hosted
version: "11.6.9"
firebase_storage_platform_interface:
dependency: transitive
description:
name: firebase_storage_platform_interface
sha256: "4a2b64d4dac096390a0b7f2e7b6d086d0546c4a1bf7ee3fc4b5ae4cc41005c46"
url: "https://pub.dev"
source: hosted
version: "5.1.12"
firebase_storage_web:
dependency: transitive
description:
name: firebase_storage_web
sha256: "4153814db8d59138e816d9f016736e4095c45675a2c18f2868d11ffd8cc6a4ca"
url: "https://pub.dev"
source: hosted
version: "3.7.3"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04
url: "https://pub.dev"
source: hosted
version: "2.0.3"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
flutter_web_plugins:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
http:
dependency: transitive
description:
name: http
sha256: a2bbf9d017fcced29139daa8ed2bba4ece450ab222871df93ca9eec6f80c34ba
url: "https://pub.dev"
source: hosted
version: "1.2.0"
http_parser:
dependency: transitive
description:
name: http_parser
sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
url: "https://pub.dev"
source: hosted
version: "4.0.2"
js:
dependency: transitive
description:
name: js
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
url: "https://pub.dev"
source: hosted
version: "0.6.7"
lints:
dependency: transitive
description:
name: lints
sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
matcher:
dependency: transitive
description:
name: matcher
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
url: "https://pub.dev"
source: hosted
version: "0.12.16"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
url: "https://pub.dev"
source: hosted
version: "0.5.0"
meta:
dependency: transitive
description:
name: meta
sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e
url: "https://pub.dev"
source: hosted
version: "1.10.0"
path:
dependency: transitive
description:
name: path
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
url: "https://pub.dev"
source: hosted
version: "1.8.3"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
url: "https://pub.dev"
source: hosted
version: "2.1.8"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.99"
source_span:
dependency: transitive
description:
name: source_span
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
url: "https://pub.dev"
source: hosted
version: "1.10.0"
stack_trace:
dependency: transitive
description:
name: stack_trace
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
url: "https://pub.dev"
source: hosted
version: "1.11.1"
stream_channel:
dependency: transitive
description:
name: stream_channel
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
url: "https://pub.dev"
source: hosted
version: "2.1.2"
string_scanner:
dependency: transitive
description:
name: string_scanner
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
url: "https://pub.dev"
source: hosted
version: "1.2.0"
term_glyph:
dependency: transitive
description:
name: term_glyph
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
url: "https://pub.dev"
source: hosted
version: "1.2.1"
test_api:
dependency: transitive
description:
name: test_api
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
url: "https://pub.dev"
source: hosted
version: "0.6.1"
typed_data:
dependency: transitive
description:
name: typed_data
sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
url: "https://pub.dev"
source: hosted
version: "1.3.2"
vector_math:
dependency: transitive
description:
name: vector_math
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
url: "https://pub.dev"
source: hosted
version: "2.1.4"
web:
dependency: transitive
description:
name: web
sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152
url: "https://pub.dev"
source: hosted
version: "0.3.0"
sdks:
dart: ">=3.2.0 <4.0.0"
flutter: ">=3.3.0"
+28
View File
@@ -0,0 +1,28 @@
name: city_repository
description: Dart package which manages the cities.
publish_to: "none"
version: 1.0.11+11
environment:
sdk: ">=2.19.3 <3.0.0"
dependencies:
flutter:
sdk: flutter
equatable: ^2.0.5
# Firebase
firebase_auth: ^4.17.4
cloud_firestore: ^4.15.4
firebase_storage: ^11.6.5
firebase_core: ^2.25.4
dev_dependencies:
flutter_lints: ^2.0.0
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
@@ -1,4 +1 @@
export 'my_user_entity.dart';
export 'country_entity.dart';
export 'region_entity.dart';
export 'city_entity.dart';
@@ -1,4 +1 @@
export 'my_user.dart';
export 'country.dart';
export 'region.dart';
export 'city.dart';
export 'my_user.dart';
@@ -1 +0,0 @@
abstract class CityRepository {}
@@ -1,7 +0,0 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'city_repo.dart';
class FirebaseCityRepository implements CityRepository {
final usersCollection = FirebaseFirestore.instance.collection('users');
}
+7
View File
@@ -89,6 +89,13 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.1"
city_repository:
dependency: "direct main"
description:
path: "packages/city_repository"
relative: true
source: path
version: "1.0.11+11"
clock:
dependency: transitive
description:
+2
View File
@@ -54,6 +54,8 @@ dependencies:
url_launcher: ^6.1.10
user_repository:
path: packages/user_repository
city_repository:
path: packages/city_repository
webview_flutter: ^4.4.1
dev_dependencies:
-30
View File
@@ -1,30 +0,0 @@
// This is a basic Flutter widget test.
//
// To perform an interaction with a widget in your test, use the WidgetTester
// utility in the flutter_test package. For example, you can send tap and scroll
// gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct.
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:prosappco/main.dart';
void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(const MainApp());
// Verify that our counter starts at 0.
expect(find.text('0'), findsOneWidget);
expect(find.text('1'), findsNothing);
// Tap the '+' icon and trigger a frame.
await tester.tap(find.byIcon(Icons.add));
await tester.pump();
// Verify that our counter has incremented.
expect(find.text('0'), findsNothing);
expect(find.text('1'), findsOneWidget);
});
}