diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index db77bb4..6ab02bc 100644 Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png index 17987b7..b89433b 100644 Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png index 09d4391..1386796 100644 Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index d5f1c8d..24d513d 100644 Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index 4d6372e..b3ff1fa 100644 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/assets/launcher.png b/assets/launcher.png new file mode 100644 index 0000000..eb8d056 Binary files /dev/null and b/assets/launcher.png differ diff --git a/l10n.yaml b/l10n.yaml new file mode 100644 index 0000000..d26d702 --- /dev/null +++ b/l10n.yaml @@ -0,0 +1,6 @@ +arb-dir: l10n +template-arb-file: app_ru.arb +output-localization-file: app_locale.dart +output-dir: lib/components/locale/l10n +output-class: AppLocale +synthetic-package: false \ No newline at end of file diff --git a/l10n/app_en.arb b/l10n/app_en.arb new file mode 100644 index 0000000..1357458 --- /dev/null +++ b/l10n/app_en.arb @@ -0,0 +1,9 @@ +{ + "@@locale": "en", + + "search": "Search", + "liked": "Like :)", + "disliked": "Dislike :(", + + "arbEnding": "" +} \ No newline at end of file diff --git a/l10n/app_ru.arb b/l10n/app_ru.arb new file mode 100644 index 0000000..9d48b01 --- /dev/null +++ b/l10n/app_ru.arb @@ -0,0 +1,9 @@ +{ + "@@locale": "ru", + + "search": "Поиск", + "liked": "Круто :)", + "disliked": "Не круто :с", + + "arbEnding": "" +} diff --git a/lib/components/extensions/context_x.dart b/lib/components/extensions/context_x.dart new file mode 100644 index 0000000..8e4a7af --- /dev/null +++ b/lib/components/extensions/context_x.dart @@ -0,0 +1,6 @@ +import 'package:flutter/widgets.dart'; +import '../locale/l10n/app_locale.dart'; + +extension LocalContextX on BuildContext { + AppLocale get locale => AppLocale.of(this)!; +} diff --git a/lib/components/utils/debounce.dart b/lib/components/utils/debounce.dart index 14e1d20..76d85f1 100644 --- a/lib/components/utils/debounce.dart +++ b/lib/components/utils/debounce.dart @@ -11,10 +11,10 @@ class Debounce { static Timer? _timer; static void run( - VoidCallback action, { - Duration delay = const Duration(milliseconds: 1000), - }) { + VoidCallback action, { + Duration delay = const Duration(milliseconds: 1000), + }) { _timer?.cancel(); _timer = Timer(delay, action); } -} \ No newline at end of file +} diff --git a/lib/data/dtos/quotes_dto.dart b/lib/data/dtos/quotes_dto.dart index cc7a6e1..73654ab 100644 --- a/lib/data/dtos/quotes_dto.dart +++ b/lib/data/dtos/quotes_dto.dart @@ -16,8 +16,9 @@ class QuoteDataDto { final String? body; final String? author; final String? imageUrl; + final String? id; - const QuoteDataDto({this.body, this.author, this.imageUrl}); + const QuoteDataDto({this.body, this.author, this.imageUrl, this.id}); factory QuoteDataDto.fromJson(Map json) => _$QuoteDataDtoFromJson(json); -} \ No newline at end of file +} diff --git a/lib/data/mappers/quotes_mapper.dart b/lib/data/mappers/quotes_mapper.dart index c4aa9e9..dc8a966 100644 --- a/lib/data/mappers/quotes_mapper.dart +++ b/lib/data/mappers/quotes_mapper.dart @@ -2,13 +2,13 @@ import '../../domain/quote.dart'; import '/data/dtos/quotes_dto.dart'; import '/presentation/home_page/home_page.dart'; -const _imagePlaceholder = - 'https://cdn-icons-png.flaticon.com/128/17818/17818874.png'; +const _imagePlaceholder = 'https://cdn-icons-png.flaticon.com/128/17818/17818874.png'; extension QuoteDtoToModel on QuoteDataDto { Quote toDomain() => Quote( - body ?? 'Без текста', - author ?? 'Неизвестный автор', - imageUrl ?? _imagePlaceholder, - ); -} \ No newline at end of file + body ?? 'Без текста', + author ?? 'Неизвестный автор', + imageUrl ?? _imagePlaceholder, + id ?? "", + ); +} diff --git a/lib/data/repositories/quotes_repository.dart b/lib/data/repositories/quotes_repository.dart index 8a816e1..39b6697 100644 --- a/lib/data/repositories/quotes_repository.dart +++ b/lib/data/repositories/quotes_repository.dart @@ -24,12 +24,10 @@ class QuotesRepository extends ApiInterface { try { final Map queryParams = {}; - if (q != null && q.isNotEmpty) { queryParams['filter'] = q; } - if (author != null && author.isNotEmpty) { queryParams['type'] = 'author'; queryParams['filter'] = author; @@ -51,4 +49,3 @@ class QuotesRepository extends ApiInterface { } } } - diff --git a/lib/domain/quote.dart b/lib/domain/quote.dart index a9448f2..fdeb240 100644 --- a/lib/domain/quote.dart +++ b/lib/domain/quote.dart @@ -2,11 +2,13 @@ class Quote { final String text; final String author; final String imagePath; + final String id; bool isFavorite; - Quote(this.text, this.author, this.imagePath, [this.isFavorite = false]); + Quote(this.text, this.author, this.imagePath, this.id,[this.isFavorite = false]); - void toggleFavorite() { + bool toggleFavorite() { isFavorite = !isFavorite; + return isFavorite; } } diff --git a/lib/main.dart b/lib/main.dart index 8d27ff6..04dd637 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,9 +1,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:pmu_flutter_labs/presentation/home_page/bloc/events.dart'; +import 'package:pmu_flutter_labs/presentation/like_bloc/like_bloc.dart'; +import 'components/locale/l10n/app_locale.dart'; import 'data/repositories/quotes_repository.dart'; import '/presentation/home_page/bloc/bloc.dart'; import '/presentation/home_page/home_page.dart'; - void main() { runApp(const MyApp()); } @@ -15,6 +17,8 @@ class MyApp extends StatelessWidget { Widget build(BuildContext context) { return MaterialApp( title: 'Цитаты', + localizationsDelegates: AppLocale.localizationsDelegates, + supportedLocales: AppLocale.supportedLocales, theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo), useMaterial3: true, @@ -22,12 +26,16 @@ class MyApp extends StatelessWidget { home: RepositoryProvider( lazy: true, create: (_) => QuotesRepository(), - child: BlocProvider( - lazy: false, - create: (context) => HomeBloc(context.read()), - child: const MyHomePage(title: "Цитаты",), + child: BlocProvider( + create: (context) => LikeBloc(), // Add LikeBloc here + child: BlocProvider( + create: (context) => HomeBloc(context.read()) + ..add(const HomeLoadDataEvent()), // Ensure initial load + child: const MyHomePage(title: "Цитаты"), + ), ), ), ); } } + diff --git a/lib/presentation/common/svg_objects.dart b/lib/presentation/common/svg_objects.dart new file mode 100644 index 0000000..1674d62 --- /dev/null +++ b/lib/presentation/common/svg_objects.dart @@ -0,0 +1,34 @@ +import 'package:flutter/widgets.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import '/components/resources.g.dart'; + +abstract class SvgObjects { + static void init() { + final pics = [ + R.ASSETS_SVG_RU_SVG, + R.ASSETS_SVG_US_SVG, + ]; + for (final String p in pics) { + final loader = SvgAssetLoader(p); + svg.cache.putIfAbsent(loader.cacheKey(null), () => loader.loadBytes(null)); + } + } +} + +class SvgRu extends StatelessWidget { + const SvgRu({super.key}); + + @override + Widget build(BuildContext context) { + return SvgPicture.asset(R.ASSETS_SVG_RU_SVG); + } +} + +class SvgUk extends StatelessWidget { + const SvgUk({super.key}); + + @override + Widget build(BuildContext context) { + return SvgPicture.asset(R.ASSETS_SVG_US_SVG); + } +} diff --git a/lib/presentation/dialogs/error_dialog.dart b/lib/presentation/dialogs/error_dialog.dart index 5431cf6..4c48f72 100644 --- a/lib/presentation/dialogs/error_dialog.dart +++ b/lib/presentation/dialogs/error_dialog.dart @@ -30,4 +30,4 @@ class ErrorDialog extends StatelessWidget { ), ); } -} \ No newline at end of file +} diff --git a/lib/presentation/dialogs/show_dialog.dart b/lib/presentation/dialogs/show_dialog.dart index 39bf3da..c73953f 100644 --- a/lib/presentation/dialogs/show_dialog.dart +++ b/lib/presentation/dialogs/show_dialog.dart @@ -2,11 +2,11 @@ import 'package:flutter/material.dart'; import 'error_dialog.dart'; void showErrorDialog( - BuildContext context, { - required String error, - }) { + BuildContext context, { + required String error, +}) { showDialog( context: context, builder: (_) => ErrorDialog(error), ); -} \ No newline at end of file +} diff --git a/lib/presentation/home_page/bloc/bloc.dart b/lib/presentation/home_page/bloc/bloc.dart index 4ea1ef4..08f10f5 100644 --- a/lib/presentation/home_page/bloc/bloc.dart +++ b/lib/presentation/home_page/bloc/bloc.dart @@ -24,12 +24,14 @@ class HomeBloc extends Bloc { } else { // Если автор указан, фильтруем данные по тексту цитаты try { - final currentData = await repo.loadData(q:search, author: author, + final currentData = await repo.loadData( + q: search, + author: author, ); final filteredData = currentData?.where((quote) { final matchesAuthor = quote.author.toLowerCase().contains(author.toLowerCase()); - final matchesSearch = search.isEmpty || - quote.text.toLowerCase().contains(search.toLowerCase()); + final matchesSearch = + search.isEmpty || quote.text.toLowerCase().contains(search.toLowerCase()); return matchesAuthor && matchesSearch; }).toList(); emit(state.copyWith(data: Future.value(filteredData))); @@ -39,13 +41,8 @@ class HomeBloc extends Bloc { } } - - - - - Future _onRefreshData(HomeRefreshEvent event, Emitter emit) async { - add(HomeLoadDataEvent(search: event.search, author: event.author)); // Просто перезапускаем загрузку + add(HomeLoadDataEvent( + search: event.search, author: event.author)); // Просто перезапускаем загрузку } - } diff --git a/lib/presentation/home_page/bloc/state.dart b/lib/presentation/home_page/bloc/state.dart index 23c6c11..3d6fb37 100644 --- a/lib/presentation/home_page/bloc/state.dart +++ b/lib/presentation/home_page/bloc/state.dart @@ -2,7 +2,6 @@ import 'package:equatable/equatable.dart'; import '../../../domain/quote.dart'; import '../home_page.dart'; - class HomeState extends Equatable { final Future>? data; // Изменено diff --git a/lib/presentation/home_page/card.dart b/lib/presentation/home_page/card.dart index b5b24f6..dcd0e56 100644 --- a/lib/presentation/home_page/card.dart +++ b/lib/presentation/home_page/card.dart @@ -1,55 +1,60 @@ import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import '../../domain/quote.dart'; +import '../like_bloc/like_bloc.dart'; +import '../like_bloc/like_state.dart'; import 'home_page.dart'; class QuoteCard extends StatelessWidget { final Quote quote; final VoidCallback onFavoriteToggle; - const QuoteCard({ - super.key, - required this.quote, - required this.onFavoriteToggle, - }); + const QuoteCard({Key? key, required this.quote, required this.onFavoriteToggle}) : super(key: key); @override Widget build(BuildContext context) { return Card( - margin: const EdgeInsets.symmetric( - vertical: 8.0, - horizontal: 10.0, - ), - child: ListTile( - contentPadding: const EdgeInsets.all(8.0), - leading: SizedBox( - width: 50.0, - child: Image.network( - quote.imagePath, - fit: BoxFit.cover, - errorBuilder: (_, __, ___) => - const Icon(Icons.error, color: Colors.red), - ), - ), - title: Text( - quote.text, - style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w500), - ), - subtitle: Text('- ${quote.author}'), - trailing: IconButton( - icon: Icon( - quote.isFavorite ? Icons.favorite : Icons.favorite_border, - color: quote.isFavorite ? Colors.red : null, - ), - onPressed: onFavoriteToggle, - ), - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => QuoteDetailScreen(quote: quote), + margin: const EdgeInsets.all(8.0), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + quote.text, + style: const TextStyle(fontSize: 18.0), ), - ); - }, + const SizedBox(height: 8.0), + Text( + '- ${quote.author}', + style: const TextStyle(fontStyle: FontStyle.italic, fontSize: 16.0), + ), + const SizedBox(height: 8.0), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ElevatedButton.icon( + onPressed: onFavoriteToggle, + icon: BlocBuilder( + builder: (context, state) { + final isLiked = state.likedIds?.contains(quote.id) ?? false; + return Icon( + isLiked ? Icons.favorite : Icons.favorite_border, + color: isLiked ? Colors.red : Colors.grey, + ); + }, + ), + label: BlocBuilder( + builder: (context, state) { + final isLiked = state.likedIds?.contains(quote.id) ?? false; + return Text(isLiked ? 'Убрать из избранного' : 'Добавить в избранное'); + }, + ), + ), + ], + ), + ], + ), ), ); } @@ -75,8 +80,7 @@ class QuoteDetailScreen extends StatelessWidget { Image.network( quote.imagePath, height: 150, - errorBuilder: (_, __, ___) => - const Icon(Icons.error, color: Colors.red), + errorBuilder: (_, __, ___) => const Icon(Icons.error, color: Colors.red), ), const SizedBox(height: 20), Text( diff --git a/lib/presentation/home_page/home_page.dart b/lib/presentation/home_page/home_page.dart index 140bab0..d9eaf78 100644 --- a/lib/presentation/home_page/home_page.dart +++ b/lib/presentation/home_page/home_page.dart @@ -1,7 +1,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:pmu_flutter_labs/components/extensions/context_x.dart'; import '../../components/utils/debounce.dart'; import '../../domain/quote.dart'; +import '../common/svg_objects.dart'; +import '../like_bloc/like_bloc.dart'; +import '../like_bloc/like_event.dart'; import '/data/repositories/quotes_repository.dart'; import '/presentation/home_page/bloc/bloc.dart'; import '/presentation/home_page/bloc/events.dart'; @@ -40,11 +44,15 @@ class _HomePageBodyState extends State<_HomePageBody> { @override void initState() { + SvgObjects.init(); super.initState(); searchController.addListener(() { Debounce.run(() { - context.read().add(HomeLoadDataEvent(search: searchController.text)); + context.read().add(HomeLoadDataEvent( + search: searchController.text, + author: authorController.text, + )); }); }); @@ -56,6 +64,18 @@ class _HomePageBodyState extends State<_HomePageBody> { )); }); }); + context.read().add(const LoadLikesEvent()); + + } + + void _showSnackbar(BuildContext context, bool isLiked) { + final message = isLiked ? context.locale.liked : context.locale.disliked; + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(message), + duration: const Duration(seconds: 2), + ), + ); } @override @@ -119,9 +139,7 @@ class _HomePageBodyState extends State<_HomePageBody> { return QuoteCard( quote: quote, onFavoriteToggle: () { - setState(() { - quote.toggleFavorite(); - }); + context.read().add(ChangeLikeEvent(quote.id)); }, ); }, @@ -136,3 +154,4 @@ class _HomePageBodyState extends State<_HomePageBody> { ); } } + diff --git a/lib/presentation/like_bloc/like_bloc.dart b/lib/presentation/like_bloc/like_bloc.dart new file mode 100644 index 0000000..490a35b --- /dev/null +++ b/lib/presentation/like_bloc/like_bloc.dart @@ -0,0 +1,36 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +//import 'package:shared_preferences/shared_preferences.dart'; + +import 'like_event.dart'; +import 'like_state.dart'; + +const String _likedPrefsKey = 'liked'; + +class LikeBloc extends Bloc { + LikeBloc() : super(const LikeState(likedIds: [])) { + on(_onChangeLike); + on(_onLoadLikes); + } + + Future _onLoadLikes(LoadLikesEvent event, Emitter emit) async { + //final prefs = await SharedPreferences.getInstance(); + //final data = prefs.getStringList(_likedPrefsKey); + + //emit(state.copyWith(likedIds: data)); + } + + Future _onChangeLike(ChangeLikeEvent event, Emitter emit) async { + final updatedList = List.from(state.likedIds ?? []); + + if (updatedList.contains(event.id)) { + updatedList.remove(event.id); + } else { + updatedList.add(event.id); + } + + //final prefs = await SharedPreferences.getInstance(); + //prefs.setStringList(_likedPrefsKey, updatedList); + + emit(state.copyWith(likedIds: updatedList)); + } +} \ No newline at end of file diff --git a/lib/presentation/like_bloc/like_event.dart b/lib/presentation/like_bloc/like_event.dart new file mode 100644 index 0000000..43032db --- /dev/null +++ b/lib/presentation/like_bloc/like_event.dart @@ -0,0 +1,13 @@ +abstract class LikeEvent { + const LikeEvent(); +} + +class LoadLikesEvent extends LikeEvent { + const LoadLikesEvent(); +} + +class ChangeLikeEvent extends LikeEvent { + final String id; + + const ChangeLikeEvent(this.id); +} \ No newline at end of file diff --git a/lib/presentation/like_bloc/like_state.dart b/lib/presentation/like_bloc/like_state.dart new file mode 100644 index 0000000..0099c7c --- /dev/null +++ b/lib/presentation/like_bloc/like_state.dart @@ -0,0 +1,14 @@ +import 'package:copy_with_extension/copy_with_extension.dart'; +import 'package:equatable/equatable.dart'; + +part 'like_state.g.dart'; + +@CopyWith() +class LikeState extends Equatable { + final List? likedIds; + + const LikeState({required this.likedIds}); + + @override + List get props => [likedIds]; +} \ No newline at end of file diff --git a/makefile b/makefile new file mode 100644 index 0000000..a15141e --- /dev/null +++ b/makefile @@ -0,0 +1,14 @@ +gen: + flutter pub run build_runner build --delete-conflicting-outputs +icon: + flutter pub run flutter_launcher_icons:main +init_res: + dart pub global activate flutter_asset_generator +format: + dart format . --line-length 100 +res: + fgen --output lib/components/resources.g.dart --no-watch --no-preview;\ + dart format . --line-length 100 +loc: + flutter gen-l10n + dart format . --line-length 100 \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index 65e7e99..6a0c31b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -26,10 +26,10 @@ packages: dependency: transitive description: name: archive - sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d + sha256: "08064924cbf0ab88280a0c3f60db9dd24fec693927e725ecb176f16c629d1cb8" url: "https://pub.dev" source: hosted - version: "3.6.1" + version: "4.0.1" args: dependency: transitive description: @@ -254,6 +254,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" + url: "https://pub.dev" + source: hosted + version: "2.1.3" file: dependency: transitive description: @@ -353,10 +361,10 @@ packages: dependency: transitive description: name: http_multi_server - sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8 url: "https://pub.dev" source: hosted - version: "3.2.1" + version: "3.2.2" http_parser: dependency: transitive description: @@ -369,10 +377,10 @@ packages: dependency: transitive description: name: image - sha256: f31d52537dc417fdcde36088fdf11d191026fd5e4fae742491ebd40e5a8bea7d + sha256: "20842a5ad1555be624c314b0c0cc0566e8ece412f61e859a42efeb6d4101a26c" url: "https://pub.dev" source: hosted - version: "4.3.0" + version: "4.5.0" intl: dependency: "direct main" description: @@ -505,10 +513,10 @@ packages: dependency: transitive description: name: package_config - sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + sha256: "92d4488434b520a62570293fbd33bb556c7d49230791c1b4bbd973baf6d2dc67" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" path: dependency: transitive description: @@ -541,6 +549,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.1" + posix: + dependency: transitive + description: + name: posix + sha256: a0117dc2167805aa9125b82eee515cc891819bac2f538c83646d355b16f58b9a + url: "https://pub.dev" + source: hosted + version: "6.0.1" pretty_dio_logger: dependency: "direct main" description: @@ -561,10 +577,10 @@ packages: dependency: transitive description: name: pub_semver - sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + sha256: "7b3cfbf654f3edd0c6298ecd5be782ce997ddf0e00531b9464b55245185bbbbd" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.5" pubspec_parse: dependency: transitive description: @@ -606,10 +622,10 @@ packages: dependency: transitive description: name: source_helper - sha256: "6adebc0006c37dd63fe05bca0a929b99f06402fc95aa35bf36d67f5c06de01fd" + sha256: "86d247119aedce8e63f4751bd9626fc9613255935558447569ad42f9f5b48b3c" url: "https://pub.dev" source: hosted - version: "1.3.4" + version: "1.3.5" source_span: dependency: transitive description: @@ -638,10 +654,10 @@ packages: dependency: transitive description: name: stream_transform - sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871 url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" string_scanner: dependency: transitive description: @@ -670,10 +686,10 @@ packages: dependency: transitive description: name: timing - sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe" url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.0.2" typed_data: dependency: transitive description: @@ -726,10 +742,10 @@ packages: dependency: transitive description: name: watcher - sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" + sha256: "69da27e49efa56a15f8afe8f4438c4ec02eff0a117df1b22ea4aad194fe1c104" url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" web: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 3d45f9b..f154479 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -7,6 +7,7 @@ environment: sdk: ^3.5.4 dependencies: + # shared_preferences: ^2.3.3 flutter: sdk: flutter @@ -29,9 +30,10 @@ dependencies: sdk: flutter intl: ^0.19.0 - #shared_preferences: ^2.0.0 + dev_dependencies: + flutter_test: sdk: flutter flutter_lints: ^5.0.0 @@ -41,9 +43,15 @@ dev_dependencies: build_runner: ^2.4.9 json_serializable: ^6.7.1 +flutter_icons: + android: "ic_launcher" + image_path: "assets/launcher.png" + min_sdk_android: 21 flutter: generate: true uses-material-design: true + assets: + - assets/svg/