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..8e19b5e 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..4b4ad5b 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..4dd15fc 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..d2e38b5 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..d305928 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/icon.png b/assets/icon.png new file mode 100644 index 0000000..1d6c516 Binary files /dev/null and b/assets/icon.png differ diff --git a/assets/svg/ru.svg b/assets/svg/ru.svg new file mode 100644 index 0000000..ae12982 --- /dev/null +++ b/assets/svg/ru.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/svg/uk.svg b/assets/svg/uk.svg new file mode 100644 index 0000000..88e2211 --- /dev/null +++ b/assets/svg/uk.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + \ No newline at end of file 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..a01051c --- /dev/null +++ b/l10n/app_en.arb @@ -0,0 +1,9 @@ +{ + "@@locale": "en", + + "search": "Search", + "liked": "liked!", + "disliked": "disliked :(", + + "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..c00dd02 --- /dev/null +++ b/l10n/app_ru.arb @@ -0,0 +1,9 @@ +{ + "@@locale": "ru", + + "search": "Поиск", + "liked": "Добавлено в понравившиеся :)", + "disliked": "Удалено из понравившегося :(", + + "arbEnding": "Чтобы не забыть про отсутствие запятой :)" +} \ No newline at end of file diff --git a/lib/Presentation/common/svg_objects.dart b/lib/Presentation/common/svg_objects.dart new file mode 100644 index 0000000..d15afce --- /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 'package:labs_petrushin/components/resources.g.dart'; + +abstract class SvgObjects { + static void init() { + final pics = [ + R.ASSETS_SVG_RU_SVG, + R.ASSETS_SVG_UK_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_UK_SVG); + } +} \ No newline at end of file diff --git a/lib/Presentation/detailPage.dart b/lib/Presentation/detailPage.dart index 2db1fab..7c0e05a 100644 --- a/lib/Presentation/detailPage.dart +++ b/lib/Presentation/detailPage.dart @@ -10,7 +10,7 @@ class DetailPage extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: const Text('Информация о продукции'), + title: const Text(''), ), body: Padding( padding: const EdgeInsets.all(16.0), @@ -31,4 +31,4 @@ class DetailPage extends StatelessWidget { ), ); } -} \ 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 19efd8f..017c689 100644 --- a/lib/Presentation/home_page/bloc/bloc.dart +++ b/lib/Presentation/home_page/bloc/bloc.dart @@ -35,4 +35,4 @@ class HomeBloc extends Bloc { error: error, )); } -} \ No newline at end of file +} diff --git a/lib/Presentation/home_page/bloc/events.dart b/lib/Presentation/home_page/bloc/events.dart index 025c2b0..cefba70 100644 --- a/lib/Presentation/home_page/bloc/events.dart +++ b/lib/Presentation/home_page/bloc/events.dart @@ -7,4 +7,4 @@ class HomeLoadDataEvent extends HomeEvent { final int? nextPage; const HomeLoadDataEvent({this.search, this.nextPage}); -} \ No newline at end of file +} diff --git a/lib/Presentation/home_page/bloc/state.dart b/lib/Presentation/home_page/bloc/state.dart index cb7ed56..f51fb67 100644 --- a/lib/Presentation/home_page/bloc/state.dart +++ b/lib/Presentation/home_page/bloc/state.dart @@ -6,23 +6,23 @@ part 'state.g.dart'; @CopyWith() class HomeState extends Equatable { - final HomeData? data; - final bool isLoading; - final bool isPaginationLoading; - final String? error; + final HomeData? data; + final bool isLoading; + final bool isPaginationLoading; + final String? error; - const HomeState({ - this.data, - this.isLoading = false, - this.isPaginationLoading = false, - this.error, - }); + const HomeState({ + this.data, + this.isLoading = false, + this.isPaginationLoading = false, + this.error, + }); - @override - List get props => [ + @override + List get props => [ data, isLoading, isPaginationLoading, error, - ]; -} \ No newline at end of file + ]; +} diff --git a/lib/Presentation/home_page/bloc/state.g.dart b/lib/Presentation/home_page/bloc/state.g.dart index 114ac25..258a914 100644 --- a/lib/Presentation/home_page/bloc/state.g.dart +++ b/lib/Presentation/home_page/bloc/state.g.dart @@ -72,8 +72,7 @@ class _$HomeStateCWProxyImpl implements _$HomeStateCWProxy { // ignore: cast_nullable_to_non_nullable : isLoading as bool, isPaginationLoading: - isPaginationLoading == const $CopyWithPlaceholder() || - isPaginationLoading == null + isPaginationLoading == const $CopyWithPlaceholder() || isPaginationLoading == null ? _value.isPaginationLoading // ignore: cast_nullable_to_non_nullable : isPaginationLoading as bool, diff --git a/lib/Presentation/home_page/home_page.dart b/lib/Presentation/home_page/home_page.dart index 86bbb85..f48e881 100644 --- a/lib/Presentation/home_page/home_page.dart +++ b/lib/Presentation/home_page/home_page.dart @@ -4,6 +4,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:labs_petrushin/Presentation/home_page/bloc/bloc.dart'; import 'package:labs_petrushin/Presentation/home_page/bloc/events.dart'; import 'package:labs_petrushin/Presentation/home_page/bloc/state.dart'; +import 'package:labs_petrushin/components/extensions/context_x.dart'; import '../../Presentation/detailPage.dart'; import '../../components/util/Debounce.dart'; import '../../repositories/food_repository.dart'; @@ -59,7 +60,6 @@ class BodyState extends State { } } - @override void dispose() { searchController.dispose(); @@ -85,32 +85,32 @@ class BodyState extends State { BlocBuilder( builder: (context, state) => state.error != null ? Text( - state.error ?? '', - style: Theme.of(context).textTheme.headlineSmall?.copyWith(color: Colors.red), - ) + state.error ?? '', + style: Theme.of(context).textTheme.headlineSmall?.copyWith(color: Colors.red), + ) : state.isLoading - ? const CircularProgressIndicator() - : Expanded( - child: RefreshIndicator( - onRefresh: _onRefresh, - child: ListView.builder( - controller: scrollController, - padding: EdgeInsets.zero, - itemCount: state.data?.data?.length ?? 0, - itemBuilder: (context, index) { - final data = state.data?.data?[index]; - return data != null - ? MyCard.fromData( - data, - onLike: (title, isLiked) => - _showSnackBar(context, title, isLiked), - onTap: () => _navToDetails(context, data), - ) - : const SizedBox.shrink(); - }, - ), - ), - ), + ? const CircularProgressIndicator() + : Expanded( + child: RefreshIndicator( + onRefresh: _onRefresh, + child: ListView.builder( + controller: scrollController, + padding: EdgeInsets.zero, + itemCount: state.data?.data?.length ?? 0, + itemBuilder: (context, index) { + final data = state.data?.data?[index]; + return data != null + ? MyCard.fromData( + data, + onLike: (title, isLiked) => + _showSnackBar(context, title, isLiked), + onTap: () => _navToDetails(context, data), + ) + : const SizedBox.shrink(); + }, + ), + ), + ), ), BlocBuilder( builder: (context, state) => state.isPaginationLoading @@ -130,7 +130,7 @@ class BodyState extends State { void _navToDetails(BuildContext context, CardData data) { Navigator.push( context, - CupertinoPageRoute(builder: (context) => DetailPage(info: data.info, imgUrl: data.urlImage)), + CupertinoPageRoute(builder: (context) => DetailPage(info: data.info, imgUrl: data.urlImage)), ); } @@ -138,7 +138,7 @@ class BodyState extends State { WidgetsBinding.instance.addPostFrameCallback((_) { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text( - '$title ${isLiked ? 'liked!' : 'disliked'}', + '$title ${isLiked ? context.locale.liked : context.locale.disliked}', style: Theme.of(context).textTheme.bodyLarge, ), backgroundColor: Colors.redAccent, @@ -146,4 +146,4 @@ class BodyState extends State { )); }); } -} \ No newline at end of file +} diff --git a/lib/Presentation/main.dart b/lib/Presentation/main.dart index f7d578d..e300647 100644 --- a/lib/Presentation/main.dart +++ b/lib/Presentation/main.dart @@ -1,10 +1,10 @@ import 'package:flutter/material.dart'; import 'package:labs_petrushin/Presentation/home_page/bloc/bloc.dart'; +import 'package:labs_petrushin/components/locale/l10n/app_locale.dart'; import 'package:labs_petrushin/repositories/food_repository.dart'; import 'home_page/home_page.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; - void main() { runApp(const MyApp()); } @@ -15,23 +15,23 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( - title: 'Petrushin demo', - theme: ThemeData( - colorScheme: ColorScheme.fromSeed(seedColor: Colors.red), - useMaterial3: true, - ), - home: RepositoryProvider( - lazy: true, - create: (_) => FoodRepository(), - child: BlocProvider( - lazy: false, - create: (context) => HomeBloc(context.read()), - child: const MyHomePage(title: 'Петрушин Егор Александрович',), - ) - ) - ); + title: 'Petrushin demo', + localizationsDelegates: AppLocale.localizationsDelegates, + supportedLocales: AppLocale.supportedLocales, + debugShowCheckedModeBanner: false, + theme: ThemeData( + colorScheme: ColorScheme.fromSeed(seedColor: Colors.red), + useMaterial3: true, + ), + home: RepositoryProvider( + lazy: true, + create: (_) => FoodRepository(), + child: BlocProvider( + lazy: false, + create: (context) => HomeBloc(context.read()), + child: const MyHomePage( + title: 'Петрушин Егор Александрович', + ), + ))); } } - - - diff --git a/lib/components/extensions/context_x.dart b/lib/components/extensions/context_x.dart new file mode 100644 index 0000000..37fb2c3 --- /dev/null +++ b/lib/components/extensions/context_x.dart @@ -0,0 +1,6 @@ +import 'package:labs_petrushin/components/locale/l10n/app_locale.dart'; +import 'package:flutter/cupertino.dart'; + +extension LocalContextX on BuildContext { + AppLocale get locale => AppLocale.of(this)!; +} \ No newline at end of file diff --git a/lib/components/locale/l10n/app_locale.dart b/lib/components/locale/l10n/app_locale.dart new file mode 100644 index 0000000..bb28342 --- /dev/null +++ b/lib/components/locale/l10n/app_locale.dart @@ -0,0 +1,153 @@ +import 'dart:async'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:intl/intl.dart' as intl; + +import 'app_locale_en.dart'; +import 'app_locale_ru.dart'; + +// ignore_for_file: type=lint + +/// Callers can lookup localized strings with an instance of AppLocale +/// returned by `AppLocale.of(context)`. +/// +/// Applications need to include `AppLocale.delegate()` in their app's +/// `localizationDelegates` list, and the locales they support in the app's +/// `supportedLocales` list. For example: +/// +/// ```dart +/// import 'l10n/app_locale.dart'; +/// +/// return MaterialApp( +/// localizationsDelegates: AppLocale.localizationsDelegates, +/// supportedLocales: AppLocale.supportedLocales, +/// home: MyApplicationHome(), +/// ); +/// ``` +/// +/// ## Update pubspec.yaml +/// +/// Please make sure to update your pubspec.yaml to include the following +/// packages: +/// +/// ```yaml +/// dependencies: +/// # Internationalization support. +/// flutter_localizations: +/// sdk: flutter +/// intl: any # Use the pinned version from flutter_localizations +/// +/// # Rest of dependencies +/// ``` +/// +/// ## iOS Applications +/// +/// iOS applications define key application metadata, including supported +/// locales, in an Info.plist file that is built into the application bundle. +/// To configure the locales supported by your app, you’ll need to edit this +/// file. +/// +/// First, open your project’s ios/Runner.xcworkspace Xcode workspace file. +/// Then, in the Project Navigator, open the Info.plist file under the Runner +/// project’s Runner folder. +/// +/// Next, select the Information Property List item, select Add Item from the +/// Editor menu, then select Localizations from the pop-up menu. +/// +/// Select and expand the newly-created Localizations item then, for each +/// locale your application supports, add a new item and select the locale +/// you wish to add from the pop-up menu in the Value field. This list should +/// be consistent with the languages listed in the AppLocale.supportedLocales +/// property. +abstract class AppLocale { + AppLocale(String locale) : localeName = intl.Intl.canonicalizedLocale(locale.toString()); + + final String localeName; + + static AppLocale? of(BuildContext context) { + return Localizations.of(context, AppLocale); + } + + static const LocalizationsDelegate delegate = _AppLocaleDelegate(); + + /// A list of this localizations delegate along with the default localizations + /// delegates. + /// + /// Returns a list of localizations delegates containing this delegate along with + /// GlobalMaterialLocalizations.delegate, GlobalCupertinoLocalizations.delegate, + /// and GlobalWidgetsLocalizations.delegate. + /// + /// Additional delegates can be added by appending to this list in + /// MaterialApp. This list does not have to be used at all if a custom list + /// of delegates is preferred or required. + static const List> localizationsDelegates = >[ + delegate, + GlobalMaterialLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + ]; + + /// A list of this localizations delegate's supported locales. + static const List supportedLocales = [ + Locale('en'), + Locale('ru') + ]; + + /// No description provided for @search. + /// + /// In ru, this message translates to: + /// **'Поиск'** + String get search; + + /// No description provided for @liked. + /// + /// In ru, this message translates to: + /// **'Добавлено в понравившиеся :)'** + String get liked; + + /// No description provided for @disliked. + /// + /// In ru, this message translates to: + /// **'Удалено из понравившегося :('** + String get disliked; + + /// No description provided for @arbEnding. + /// + /// In ru, this message translates to: + /// **'Чтобы не забыть про отсутствие запятой :)'** + String get arbEnding; +} + +class _AppLocaleDelegate extends LocalizationsDelegate { + const _AppLocaleDelegate(); + + @override + Future load(Locale locale) { + return SynchronousFuture(lookupAppLocale(locale)); + } + + @override + bool isSupported(Locale locale) => ['en', 'ru'].contains(locale.languageCode); + + @override + bool shouldReload(_AppLocaleDelegate old) => false; +} + +AppLocale lookupAppLocale(Locale locale) { + + + // Lookup logic when only language code is specified. + switch (locale.languageCode) { + case 'en': return AppLocaleEn(); + case 'ru': return AppLocaleRu(); + } + + throw FlutterError( + 'AppLocale.delegate failed to load unsupported locale "$locale". This is likely ' + 'an issue with the localizations generation tool. Please file an issue ' + 'on GitHub with a reproducible sample app and the gen-l10n configuration ' + 'that was used.' + ); +} diff --git a/lib/components/locale/l10n/app_locale_en.dart b/lib/components/locale/l10n/app_locale_en.dart new file mode 100644 index 0000000..599548c --- /dev/null +++ b/lib/components/locale/l10n/app_locale_en.dart @@ -0,0 +1,20 @@ +import 'app_locale.dart'; + +// ignore_for_file: type=lint + +/// The translations for English (`en`). +class AppLocaleEn extends AppLocale { + AppLocaleEn([String locale = 'en']) : super(locale); + + @override + String get search => 'Search'; + + @override + String get liked => 'liked!'; + + @override + String get disliked => 'disliked :('; + + @override + String get arbEnding => 'Чтобы не забыть про отсутствие запятой :)'; +} diff --git a/lib/components/locale/l10n/app_locale_ru.dart b/lib/components/locale/l10n/app_locale_ru.dart new file mode 100644 index 0000000..fbd2661 --- /dev/null +++ b/lib/components/locale/l10n/app_locale_ru.dart @@ -0,0 +1,20 @@ +import 'app_locale.dart'; + +// ignore_for_file: type=lint + +/// The translations for Russian (`ru`). +class AppLocaleRu extends AppLocale { + AppLocaleRu([String locale = 'ru']) : super(locale); + + @override + String get search => 'Поиск'; + + @override + String get liked => 'Добавлено в понравившиеся :)'; + + @override + String get disliked => 'Удалено из понравившегося :('; + + @override + String get arbEnding => 'Чтобы не забыть про отсутствие запятой :)'; +} diff --git a/lib/components/resources.g.dart b/lib/components/resources.g.dart new file mode 100644 index 0000000..9645894 --- /dev/null +++ b/lib/components/resources.g.dart @@ -0,0 +1,10 @@ +/// Generate by [asset_generator](https://github.com/fluttercandies/flutter_asset_generator) library. +/// PLEASE DO NOT EDIT MANUALLY. +// ignore_for_file: constant_identifier_names +class R { + const R._(); + + static const String ASSETS_SVG_RU_SVG = 'assets/svg/ru.svg'; + + static const String ASSETS_SVG_UK_SVG = 'assets/svg/uk.svg'; +} diff --git a/lib/components/util/Debounce.dart b/lib/components/util/Debounce.dart index b4e1f35..6e1c470 100644 --- a/lib/components/util/Debounce.dart +++ b/lib/components/util/Debounce.dart @@ -10,11 +10,11 @@ class Debounce { static Timer? _timer; - static void run ( - VoidCallback action, { - Duration delay = const Duration(milliseconds: 500), - }) { + static void run( + VoidCallback action, { + Duration delay = const Duration(milliseconds: 500), + }) { _timer?.cancel(); _timer = Timer(delay, action); } -} \ No newline at end of file +} diff --git a/lib/data/dtos/foods_dto.dart b/lib/data/dtos/foods_dto.dart index 9c63744..842370e 100644 --- a/lib/data/dtos/foods_dto.dart +++ b/lib/data/dtos/foods_dto.dart @@ -14,7 +14,6 @@ class FoodsDto { const FoodsDto({this.foods, this.currentPage, this.totalPages}); factory FoodsDto.fromJson(Map json) => _$FoodsDtoFromJson(json); - } @JsonSerializable(createToJson: false) @@ -27,4 +26,4 @@ class FoodDataDto { const FoodDataDto({this.fdcId, this.brandName, this.description, this.image}); factory FoodDataDto.fromJson(Map json) => _$FoodDataDtoFromJson(json); -} \ No newline at end of file +} diff --git a/lib/data/mappers/food_mapper.dart b/lib/data/mappers/food_mapper.dart index 86d049e..e5bc0ad 100644 --- a/lib/data/mappers/food_mapper.dart +++ b/lib/data/mappers/food_mapper.dart @@ -1,4 +1,3 @@ - import 'package:labs_petrushin/Presentation/home_page/home_page.dart'; import 'package:labs_petrushin/data/dtos/foods_dto.dart'; @@ -6,9 +5,7 @@ import '../../domain/models/home.dart'; extension CharacterDataDtoToModel on FoodDataDto { CardData toDomain() => CardData( - text: brandName ?? "Просто хлэп", - info: description ?? "Очень кусьна", - urlImage: image); + text: brandName ?? "Просто хлэп", info: description ?? "Очень кусьна", urlImage: image); } extension CharactersDtoToModel on FoodsDto { @@ -24,4 +21,4 @@ extension CharactersDtoToModel on FoodsDto { nextPage: nextPage, ); } -} \ No newline at end of file +} diff --git a/lib/domain/models/card.dart b/lib/domain/models/card.dart index e93be9b..91d2ff3 100644 --- a/lib/domain/models/card.dart +++ b/lib/domain/models/card.dart @@ -17,15 +17,21 @@ class MyCard extends StatefulWidget { final OnLikeCallback onLike; final VoidCallback? onTap; - const MyCard({super.key, required this.text, required this.info, required this.urlImage, this.onLike, this.onTap}); + const MyCard( + {super.key, + required this.text, + required this.info, + required this.urlImage, + this.onLike, + this.onTap}); factory MyCard.fromData(CardData data, {OnLikeCallback onLike, VoidCallback? onTap}) => MyCard( - text: data.text, - info: data.info, - urlImage: data.urlImage, - onLike: onLike, - onTap: onTap, - ); + text: data.text, + info: data.info, + urlImage: data.urlImage, + onLike: onLike, + onTap: onTap, + ); @override State createState() => _MyCardState(); @@ -59,7 +65,8 @@ class _MyCardState extends State { height: double.infinity, width: 160, child: Image.network( - widget.urlImage ?? 'https://hlebzavod3.ru/images/virtuemart/product/011_IMG_9657.jpg', + widget.urlImage ?? + 'https://hlebzavod3.ru/images/virtuemart/product/011_IMG_9657.jpg', fit: BoxFit.cover, errorBuilder: (_, __, ___) => const Placeholder(), ), @@ -102,14 +109,14 @@ class _MyCardState extends State { duration: const Duration(milliseconds: 300), child: isLiked ? const Icon( - Icons.favorite, - color: Colors.redAccent, - key: ValueKey(0), - ) + Icons.favorite, + color: Colors.redAccent, + key: ValueKey(0), + ) : const Icon( - Icons.favorite_border, - key: ValueKey(1), - ), + Icons.favorite_border, + key: ValueKey(1), + ), ), ), ), @@ -120,4 +127,4 @@ class _MyCardState extends State { ), ); } -} \ No newline at end of file +} diff --git a/lib/domain/models/home.dart b/lib/domain/models/home.dart index 2003426..3ffc102 100644 --- a/lib/domain/models/home.dart +++ b/lib/domain/models/home.dart @@ -1,4 +1,3 @@ - import '../../Presentation/home_page/home_page.dart'; class HomeData { @@ -6,4 +5,4 @@ class HomeData { final int? nextPage; HomeData({this.data, this.nextPage}); -} \ No newline at end of file +} diff --git a/lib/repositories/api_interface.dart b/lib/repositories/api_interface.dart index 5ea086a..6e0bfc7 100644 --- a/lib/repositories/api_interface.dart +++ b/lib/repositories/api_interface.dart @@ -1,8 +1,7 @@ - import 'package:labs_petrushin/Presentation/home_page/home_page.dart'; import '../domain/models/home.dart'; abstract class ApiInterface { Future loadData(); -} \ No newline at end of file +} diff --git a/lib/repositories/food_repository.dart b/lib/repositories/food_repository.dart index 116187e..4422c60 100644 --- a/lib/repositories/food_repository.dart +++ b/lib/repositories/food_repository.dart @@ -1,4 +1,3 @@ - import 'package:dio/dio.dart'; import 'package:labs_petrushin/Presentation/home_page/home_page.dart'; import 'package:labs_petrushin/data/dtos/foods_dto.dart'; @@ -10,11 +9,10 @@ import '../domain/models/home.dart'; class FoodRepository extends ApiInterface { static final Dio _dio = Dio() - ..interceptors.add( - PrettyDioLogger( - requestHeader: true, - requestBody: true, - )); + ..interceptors.add(PrettyDioLogger( + requestHeader: true, + requestBody: true, + )); // 91xPcWwfSGljSRMuoS8IH0GP4hM9QqwwtgSzqJMw static const String _baseUrl = 'https://api.nal.usda.gov'; @@ -23,7 +21,8 @@ class FoodRepository extends ApiInterface { Future loadData({String? q, int page = 1, int pageSize = 10}) async { try { final String searchQuery = q ?? ''; // Используем 'food' как значение по умолчанию - final String url = '$_baseUrl/fdc/v1/foods/search?api_key=91xPcWwfSGljSRMuoS8IH0GP4hM9QqwwtgSzqJMw&query=$searchQuery&pageNumber=$page&pageSize=$pageSize'; + final String url = + '$_baseUrl/fdc/v1/foods/search?api_key=91xPcWwfSGljSRMuoS8IH0GP4hM9QqwwtgSzqJMw&query=$searchQuery&pageNumber=$page&pageSize=$pageSize'; final Response response = await _dio.get>(url); @@ -36,4 +35,4 @@ class FoodRepository extends ApiInterface { return null; } } -} \ No newline at end of file +} diff --git a/makefile b/makefile new file mode 100644 index 0000000..cb6377b --- /dev/null +++ b/makefile @@ -0,0 +1,23 @@ +gen: + flutter pub run build_runner build --delete-conflicting-outputs + +hello: + echo "Hi!"; \ + echo "I'm makefile"; \ + echo "^_^" + +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; \ + make format + +loc: + flutter gen-l10n \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index f962be0..d736713 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -22,6 +22,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.7.0" + archive: + dependency: transitive + description: + name: archive + sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d + url: "https://pub.dev" + source: hosted + version: "3.6.1" args: dependency: transitive description: @@ -134,6 +142,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.3" + cli_util: + dependency: transitive + description: + name: cli_util + sha256: c05b7406fdabc7a49a3929d4af76bcaccbbffcbcdcf185b082e1ae07da323d19 + url: "https://pub.dev" + source: hosted + version: "0.4.1" clock: dependency: transitive description: @@ -238,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: @@ -267,6 +291,14 @@ packages: url: "https://pub.dev" source: hosted version: "8.1.6" + flutter_launcher_icons: + dependency: "direct dev" + description: + name: flutter_launcher_icons + sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea" + url: "https://pub.dev" + source: hosted + version: "0.13.1" flutter_lints: dependency: "direct dev" description: @@ -275,11 +307,29 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.0" + flutter_localizations: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: "8c5d68a82add3ca76d792f058b186a0599414f279f00ece4830b9b231b570338" + url: "https://pub.dev" + source: hosted + version: "2.0.7" 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" frontend_server_client: dependency: transitive description: @@ -304,6 +354,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.2" + http: + dependency: transitive + description: + name: http + sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 + url: "https://pub.dev" + source: hosted + version: "1.2.2" http_multi_server: dependency: transitive description: @@ -320,6 +378,22 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" + image: + dependency: transitive + description: + name: image + sha256: f31d52537dc417fdcde36088fdf11d191026fd5e4fae742491ebd40e5a8bea7d + url: "https://pub.dev" + source: hosted + version: "4.3.0" + intl: + dependency: "direct main" + description: + name: intl + sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf + url: "https://pub.dev" + source: hosted + version: "0.19.0" io: dependency: transitive description: @@ -456,6 +530,62 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.0" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf + url: "https://pub.dev" + source: hosted + version: "1.0.1" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 + url: "https://pub.dev" + source: hosted + version: "2.3.0" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 + url: "https://pub.dev" + source: hosted + version: "6.0.2" + platform: + dependency: transitive + description: + name: platform + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" + url: "https://pub.dev" + source: hosted + version: "3.1.6" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" pool: dependency: transitive description: @@ -496,6 +626,62 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180 + url: "https://pub.dev" + source: hosted + version: "2.2.3" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + sha256: "3b9febd815c9ca29c9e3520d50ec32f49157711e143b7a4ca039eb87e8ade5ab" + url: "https://pub.dev" + source: hosted + version: "2.3.3" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + sha256: "07e050c7cd39bad516f8d64c455f04508d09df104be326d8c02551590a0d513d" + url: "https://pub.dev" + source: hosted + version: "2.5.3" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + sha256: d2ca4132d3946fec2184261726b355836a82c33d7d5b67af32692aff18a4684e + url: "https://pub.dev" + source: hosted + version: "2.4.2" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" + url: "https://pub.dev" + source: hosted + version: "2.4.1" shelf: dependency: transitive description: @@ -605,6 +791,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.0" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: "32c3c684e02f9bc0afb0ae0aa653337a2fe022e8ab064bcd7ffda27a74e288e3" + url: "https://pub.dev" + source: hosted + version: "1.1.11+1" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: c86987475f162fadff579e7320c7ddda04cd2fdeffbe1129227a85d9ac9e03da + url: "https://pub.dev" + source: hosted + version: "1.1.11+1" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: "12faff3f73b1741a36ca7e31b292ddeb629af819ca9efe9953b70bd63fc8cd81" + url: "https://pub.dev" + source: hosted + version: "1.1.11+1" vector_math: dependency: transitive description: @@ -653,6 +863,22 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.1" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + xml: + dependency: transitive + description: + name: xml + sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 + url: "https://pub.dev" + source: hosted + version: "6.5.0" yaml: dependency: transitive description: @@ -663,4 +889,4 @@ packages: version: "3.1.2" sdks: dart: ">=3.5.2 <4.0.0" - flutter: ">=3.18.0-18.0.pre.54" + flutter: ">=3.24.0" diff --git a/pubspec.yaml b/pubspec.yaml index bcc4f56..a00c2ab 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: labs_petrushin description: "A new Flutter project." publish_to: 'none' # Remove this line if you wish to publish to pub.dev - +version: 1.0.0+1 environment: sdk: ^3.5.2 @@ -16,9 +16,14 @@ dependencies: equatable: ^2.0.5 flutter_bloc: ^8.1.5 copy_with_extension_gen: ^5.0.4 - # The following adds the Cupertino Icons font to your application. - # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.8 + flutter_svg: 2.0.7 + + flutter_localizations: + sdk: flutter + intl: ^0.19.0 + + shared_preferences: 2.2.3 dev_dependencies: flutter_test: @@ -26,20 +31,18 @@ dev_dependencies: build_runner: ^2.4.9 json_serializable: ^6.7.1 - # The "flutter_lints" package below contains a set of recommended lints to - # encourage good coding practices. The lint set provided by the package is - # activated in the `analysis_options.yaml` file located at the root of your - # package. See that file for information about deactivating specific lint - # rules and activating additional ones. flutter_lints: ^4.0.0 -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec + flutter_launcher_icons: 0.13.1 + +flutter_icons: + android: "ic_launcher" + ios: false + image_path: "assets/icon.png" + min_sdk_android: 21 -# The following section is specific to Flutter packages. flutter: - - # The following line ensures that the Material Icons font is - # included with your application, so that you can use the icons in - # the material Icons class. uses-material-design: true + generate: true + assets: + - assets/svg/