This commit is contained in:
Владимир Данилов 2024-12-21 07:05:58 +04:00
parent 87a0be61f6
commit 697e7d1da5
27 changed files with 648 additions and 287 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 544 B

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 442 B

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 721 B

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 62 KiB

View File

@ -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_US_SVG = 'assets/svg/us.svg';
}

View File

@ -11,10 +11,10 @@ class Debounce {
static Timer? _timer;
static void run(
VoidCallback action, {
Duration delay = const Duration(milliseconds: 500),
}) {
VoidCallback action, {
Duration delay = const Duration(milliseconds: 500),
}) {
_timer?.cancel();
_timer = Timer(delay, action);
}
}
}

View File

@ -4,16 +4,19 @@ part 'characters_dto.g.dart';
@JsonSerializable(createToJson: false)
class CharactersDto {
final List<CharacterDataDto>? data;
final PaginationDto? pagination;
final List<CharacterDataDto>? results;
final PaginationDto? info;
const CharactersDto({this.data, this.pagination,});
const CharactersDto({
this.results,
this.info,
});
factory CharactersDto.fromJson(Map<String, dynamic> json) => _$CharactersDtoFromJson(json);
}
@JsonSerializable(createToJson: false)
class CharacterDataDto{
class CharacterDataDto {
final int? id;
final String? name;
final String? status;
@ -51,4 +54,4 @@ class PaginationDto {
final page = uri.queryParameters['page'];
return page != null ? int.tryParse(page) : null;
}
}
}

View File

@ -3,27 +3,28 @@ import 'package:flutter_labs_app/domain/models/card.dart';
import '../../domain/models/home.dart';
extension CharacterDataDtoModel on CharacterDataDto{
extension CharacterDataDtoModel on CharacterDataDto {
CardDate toDomain() => CardDate(
name ?? 'UNKNOW',
imageUrl: image,
descriptionText: _makeDescriptionText(species, status),
);
name ?? 'UNKNOW',
imageUrl: image,
descriptionText: _makeDescriptionText(species, status),
id: id.toString(),
);
String _makeDescriptionText(String? species, String? status){
String _makeDescriptionText(String? species, String? status) {
return species != null && status != null
? 'species: $species \n status: $status'
: species != null
? 'species: $species'
:status != null
? 'status: $status'
: '';
? 'species: $species'
: status != null
? 'status: $status'
: '';
}
}
extension CharactersDataDtoModel on CharactersDto {
HomeData toDomain() => HomeData(
data: data?.map((e) => e.toDomain()).toList(),
nextPage: pagination?.next,
);
}
data: results?.map((e) => e.toDomain()).toList(),
nextPage: info?.next,
);
}

View File

@ -3,6 +3,6 @@ import 'package:flutter_labs_app/domain/models/home.dart';
typedef OnErrorCallback = void Function(String? error);
abstract class ApiInterface{
abstract class ApiInterface {
Future<HomeData?> loadData({OnErrorCallback? onError});
}
}

View File

@ -3,34 +3,37 @@ import 'package:flutter_labs_app/data/repositories/api_interface.dart';
import 'package:flutter_labs_app/domain/models/card.dart';
import 'package:flutter_labs_app/domain/models/home.dart';
class MockRepository extends ApiInterface{
class MockRepository extends ApiInterface {
@override
Future<HomeData?> loadData({OnErrorCallback? onError}) async{
Future<HomeData?> loadData({OnErrorCallback? onError}) async {
return HomeData(
data: [
CardDate(
'Hi',
descriptionText: 'hello',
icon: Icons.h_mobiledata_sharp,
imageUrl: 'https://avatars.mds.yandex.net/i?id=7cb577fccf8b7354b5248cb8101dd09433fa521f-4253662-images-thumbs&n=13',
),
CardDate(
'Privet',
descriptionText: 'hello',
icon: Icons.pages,
imageUrl: 'https://avatars.mds.yandex.net/i?id=34f57633c955c47b56c68537076e5bfabb4a397b-4577841-images-thumbs&n=13',
),
CardDate(
'Arigato',
descriptionText: 'hello',
icon: Icons.account_tree_sharp,
imageUrl: 'https://avatars.mds.yandex.net/i?id=d3e8f5e5c373aec40e18fdb5bc28f98367e0f0d9-4271037-images-thumbs&n=13',
),
CardDate(
'Last',
descriptionText: 'hello',
)
],
CardDate(
'Hi',
descriptionText: 'hello',
icon: Icons.h_mobiledata_sharp,
imageUrl:
'https://avatars.mds.yandex.net/i?id=7cb577fccf8b7354b5248cb8101dd09433fa521f-4253662-images-thumbs&n=13',
),
CardDate(
'Privet',
descriptionText: 'hello',
icon: Icons.pages,
imageUrl:
'https://avatars.mds.yandex.net/i?id=34f57633c955c47b56c68537076e5bfabb4a397b-4577841-images-thumbs&n=13',
),
CardDate(
'Arigato',
descriptionText: 'hello',
icon: Icons.account_tree_sharp,
imageUrl:
'https://avatars.mds.yandex.net/i?id=d3e8f5e5c373aec40e18fdb5bc28f98367e0f0d9-4271037-images-thumbs&n=13',
),
CardDate(
'Last',
descriptionText: 'hello',
)
],
);
}
}
}

View File

@ -6,7 +6,7 @@ import 'package:flutter_labs_app/domain/models/card.dart';
import 'package:flutter_labs_app/domain/models/home.dart';
import 'package:pretty_dio_logger/pretty_dio_logger.dart';
class RickRepository extends ApiInterface{
class RickRepository extends ApiInterface {
static final Dio _dio = Dio()
..interceptors.add(PrettyDioLogger(
requestHeader: true,
@ -22,23 +22,23 @@ class RickRepository extends ApiInterface{
int page = 1,
int pageSize = 20,
}) async {
try{
try {
const String url = '$_baseUrl/api/character';
final Response<dynamic> response = await _dio.get<Map<dynamic, dynamic>>(
url,
queryParameters: {
'name': q,
'page': page,
},
url,
queryParameters: {
'name': q,
'page': page,
},
);
final CharactersDto dto = CharactersDto.fromJson(response.data as Map<String, dynamic>);
final HomeData? data = dto.toDomain();
return data;
} on DioException catch (e){
} on DioException catch (e) {
onError?.call(e.error?.toString());
return null;
}
}
}
}

View File

@ -1,16 +1,17 @@
import 'package:flutter/material.dart';
class CardDate{
class CardDate {
final String text;
final String descriptionText;
final IconData icon;
final String? imageUrl;
final String? id;
CardDate(
this.text,
{
required this.descriptionText,
this.icon = Icons.ac_unit_outlined,
this.imageUrl = 'https://via.placeholder.com/150',
});
}
this.text, {
required this.descriptionText,
this.icon = Icons.ac_unit_outlined,
this.imageUrl = 'https://via.placeholder.com/150',
this.id,
});
}

View File

@ -5,4 +5,4 @@ class HomeData {
final int? nextPage;
HomeData({this.data, this.nextPage});
}
}

View File

@ -1,8 +1,15 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_labs_app/data/repositories/rick_repository.dart';
import 'package:flutter_labs_app/presentation/home_page/bloc/bloc.dart';
import 'package:flutter_labs_app/presentation/home_page/home_page.dart';
import 'package:flutter_labs_app/presentation/like_bloc/like_bloc.dart';
import 'package:flutter_labs_app/presentation/locale_bloc/locale_bloc.dart';
import 'package:flutter_labs_app/presentation/locale_bloc/locale_state.dart';
import 'components/locale/l10n/app_locale.dart';
void main() {
runApp(const MyApp());
@ -13,21 +20,36 @@ class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.limeAccent),
useMaterial3: true,
),
home: RepositoryProvider<RickRepository>(
lazy: true,
create: (_) => RickRepository(),
child: BlocProvider<HomeBloc>(
lazy: false,
create: (context) => HomeBloc(context.read<RickRepository>()),
child: const MyHomePage(title: 'Danilov V.V.'),
),
return BlocProvider<LocaleBloc>(
lazy: false,
create: (context) => LocaleBloc(Locale(Platform.localeName)),
child: BlocBuilder<LocaleBloc, LocaleState>(
builder: (context, state) {
return MaterialApp(
title: 'Flutter Demo',
locale: state.currentLocale,
localizationsDelegates: AppLocale.localizationsDelegates,
supportedLocales: AppLocale.supportedLocales,
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.limeAccent),
useMaterial3: true,
),
home: RepositoryProvider<RickRepository>(
lazy: true,
create: (_) => RickRepository(),
child: BlocProvider<LikeBloc>(
lazy: false,
create: (context) => LikeBloc(),
child: BlocProvider<HomeBloc>(
lazy: false,
create: (context) => HomeBloc(context.read<RickRepository>()),
child: const MyHomePage(title: 'Danilov V.V.'),
),
),
),
);
},
),
);
}

View File

@ -0,0 +1,35 @@
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 = <String>[
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);
}
}

View File

@ -1,13 +1,13 @@
import 'package:flutter/material.dart';
import 'package:flutter_labs_app/domain/models/card.dart';
class DetailsPage extends StatelessWidget{
class DetailsPage extends StatelessWidget {
final CardDate data;
const DetailsPage(this.data, {super.key});
@override
Widget build(BuildContext context){
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
@ -36,4 +36,4 @@ class DetailsPage extends StatelessWidget{
),
);
}
}
}

View File

@ -25,7 +25,7 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
onError: (e) => error = e,
);
if (event.nextPage != null){
if (event.nextPage != null) {
data?.data?.insertAll(0, state.data?.data ?? []);
}
@ -36,4 +36,4 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
error: error,
));
}
}
}

View File

@ -1,10 +1,10 @@
abstract class HomeEvent{
abstract class HomeEvent {
const HomeEvent();
}
class HomeLoadDataEvent extends HomeEvent{
class HomeLoadDataEvent extends HomeEvent {
final String? search;
final int? nextPage;
const HomeLoadDataEvent({this.search, this.nextPage});
}
}

View File

@ -30,9 +30,9 @@ class HomeState extends Equatable {
@override
List<Object?> get props => [
data,
isLoading,
isPaginationLoading,
error,
];
}
data,
isLoading,
isPaginationLoading,
error,
];
}

View File

@ -1,50 +1,48 @@
part of 'home_page.dart';
typedef OnLikeCallback = void Function(String title, bool isLiked)?;
typedef OnLikeCallback = void Function(String? id, String title, bool isLiked)?;
class _Card extends StatefulWidget {
class _Card extends StatelessWidget {
final String text;
final String descriptionText;
final IconData icon;
final String? imageUrl;
final OnLikeCallback onLike;
final VoidCallback? onTap;
final String? id;
final bool isLiked;
const _Card(
this.text,
{
required this.descriptionText,
this.icon = Icons.ac_unit_outlined,
this.imageUrl,
this.onLike,
this.onTap
}
);
const _Card(this.text,
{required this.descriptionText,
this.icon = Icons.ac_unit_outlined,
this.imageUrl,
this.onLike,
this.onTap,
this.id,
this.isLiked = false,
});
factory _Card.fromData(
CardDate data, {
OnLikeCallback onLike,
VoidCallback? onTap,
}) => _Card(
data.text,
descriptionText: data.descriptionText,
icon: data.icon,
imageUrl: data.imageUrl,
onLike: onLike,
onTap: onTap,
);
@override
State<_Card> createState() => _CardState();
}
class _CardState extends State<_Card> {
bool isLiked = false;
CardDate data, {
OnLikeCallback onLike,
VoidCallback? onTap,
bool isLiked = false,
}) =>
_Card(
data.text,
descriptionText: data.descriptionText,
icon: data.icon,
imageUrl: data.imageUrl,
onLike: onLike,
onTap: onTap,
id: data.id,
isLiked: isLiked,
);
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: widget.onTap,
onTap: onTap,
child: Container(
margin: const EdgeInsets.all(16),
constraints: const BoxConstraints(minHeight: 140),
@ -61,10 +59,8 @@ class _CardState extends State<_Card> {
spreadRadius: 4,
offset: const Offset(0, 5),
blurRadius: 8,
blurStyle: BlurStyle.normal
)
]
),
blurStyle: BlurStyle.normal)
]),
child: IntrinsicHeight(
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
@ -78,7 +74,7 @@ class _CardState extends State<_Card> {
height: double.infinity,
width: 120,
child: Image.network(
widget.imageUrl ?? '',
imageUrl ?? '',
fit: BoxFit.cover,
),
),
@ -90,43 +86,34 @@ class _CardState extends State<_Card> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.text,
text,
style: Theme.of(context).textTheme.headlineLarge,
),
Text(
widget.descriptionText,
style: Theme.of(context).textTheme.bodyLarge
),
Text(descriptionText, style: Theme.of(context).textTheme.bodyLarge),
],
),
),
),
Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8.0),
child: Icon(widget.icon),
child: Icon(icon),
),
Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8.0),
child: GestureDetector(
onTap: (){
setState(() {
isLiked = !isLiked;
});
widget.onLike?.call(widget.text, isLiked);
},
onTap: () => onLike?.call(id, text, isLiked),
child: AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
child: isLiked
?const Icon(
? const Icon(
Icons.favorite,
color: Colors.redAccent,
key: ValueKey<int>(0),
)
:const Icon(
: const Icon(
Icons.favorite_border,
key: ValueKey<int>(1),
),
@ -137,8 +124,7 @@ class _CardState extends State<_Card> {
),
],
),
)
),
)),
);
}
}
}

View File

@ -1,12 +1,20 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_labs_app/components/extensions/context_x.dart';
import 'package:flutter_labs_app/data/repositories/mock_repository.dart';
import 'package:flutter_labs_app/data/repositories/rick_repository.dart';
import 'package:flutter_labs_app/presentation/details_page/details_page.dart';
import '../../components/utils/debounce.dart';
import '../../domain/models/card.dart';
import '../common/svg_objects.dart';
import '../like_bloc/like_bloc.dart';
import '../like_bloc/like_event.dart';
import '../like_bloc/like_state.dart';
import '../locale_bloc/locale_bloc.dart';
import '../locale_bloc/locale_events.dart';
import '../locale_bloc/locale_state.dart';
import 'bloc/bloc.dart';
import 'bloc/events.dart';
import 'bloc/state.dart';
@ -48,8 +56,11 @@ class _BodyState extends State<Body> {
@override
void initState() {
SvgObjects.init();
WidgetsBinding.instance.addPostFrameCallback((_) {
context.read<HomeBloc>().add(const HomeLoadDataEvent());
context.read<LikeBloc>().add(const LoadLikesEvent());
});
scrollController.addListener(_onNextPageListener);
@ -60,9 +71,8 @@ class _BodyState extends State<Body> {
if (scrollController.position.atEdge) {
final bloc = context.read<HomeBloc>();
if (!bloc.state.isPaginationLoading) {
bloc.add(HomeLoadDataEvent(
search: searchController.text,
nextPage: bloc.state.data?.nextPage));
bloc.add(
HomeLoadDataEvent(search: searchController.text, nextPage: bloc.state.data?.nextPage));
}
}
}
@ -81,7 +91,7 @@ class _BodyState extends State<Body> {
WidgetsBinding.instance.addPostFrameCallback((_) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(
'Лайк на $title ${isLiked ? 'поставлен' : 'убран'}',
'$title ${isLiked ? context.locale.liked : context.locale.disliked}',
style: Theme.of(context).textTheme.bodyLarge,
),
backgroundColor: Colors.orangeAccent,
@ -91,14 +101,11 @@ class _BodyState extends State<Body> {
}
void _navToDetails(BuildContext context, CardDate data) {
Navigator.push(
context, CupertinoPageRoute(builder: (context) => DetailsPage(data)));
Navigator.push(context, CupertinoPageRoute(builder: (context) => DetailsPage(data)));
}
Future<void> _onRefresh() {
context
.read<HomeBloc>()
.add(HomeLoadDataEvent(search: searchController.text));
context.read<HomeBloc>().add(HomeLoadDataEvent(search: searchController.text));
return Future.value(null);
}
@ -108,45 +115,72 @@ class _BodyState extends State<Body> {
padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(12),
child: CupertinoSearchTextField(
controller: searchController,
onChanged: (search) {
Debounce.run(() => context
.read<HomeBloc>()
.add(HomeLoadDataEvent(search: search)));
})),
Row(
children: [
Expanded(
flex: 4,
child: Padding(
padding: const EdgeInsets.all(12),
child: CupertinoSearchTextField(
controller: searchController,
placeholder: context.locale.search,
onChanged: (search) {
Debounce.run(
() => context.read<HomeBloc>().add(HomeLoadDataEvent(search: search)));
})),
),
GestureDetector(
onTap: () =>
context.read<LocaleBloc>().add(const ChangeLocaleEvent()),
child: SizedBox.square(
dimension: 50,
child: Padding(
padding: const EdgeInsets.only(right: 12),
child: BlocBuilder<LocaleBloc, LocaleState>(
builder: (context, state) {
return state.currentLocale.languageCode == 'ru'
? const SvgRu()
: const SvgUk();
},
),
),
),
),
],
),
BlocBuilder<HomeBloc, HomeState>(
builder: (context, state) => state.error != null
? Text(
state.error ?? '',
style: Theme.of(context).textTheme.headlineSmall?.copyWith(color: Colors.red),
)
: state.isLoading
? 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
? _Card.fromData(
data,
onLike: (title, isLiked) =>
_showSnackbar(
context, title, isLiked),
onTap: () =>
_navToDetails(context, data),
)
: const SizedBox.shrink();
}),
),
)),
? Text(
state.error ?? '',
style:
Theme.of(context).textTheme.headlineSmall?.copyWith(color: Colors.red),
)
: state.isLoading
? CircularProgressIndicator()
: BlocBuilder<LikeBloc, LikeState>(
builder: (context, likeState) => 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
? _Card.fromData(
data,
onLike: _onLike,
isLiked: likeState.likedIds?.contains(data.id) == true,
onTap: () => _navToDetails(context, data),
)
: const SizedBox.shrink();
}
),
),
)
)
),
BlocBuilder<HomeBloc, HomeState>(
builder: (context, state) => state.isPaginationLoading
? const CircularProgressIndicator()
@ -154,4 +188,12 @@ class _BodyState extends State<Body> {
],
));
}
}
void _onLike(String? id, String title, bool isLiked) {
print("$id $title, $isLiked");
if (id != null) {
context.read<LikeBloc>().add(ChangeLikeEvent(id));
_showSnackbar(context, title, !isLiked);
}
}
}

View File

@ -0,0 +1,56 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'like_state.dart';
// **************************************************************************
// CopyWithGenerator
// **************************************************************************
abstract class _$LikeStateCWProxy {
LikeState likedIds(List<String>? likedIds);
/// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `LikeState(...).copyWith.fieldName(...)` to override fields one at a time with nullification support.
///
/// Usage
/// ```dart
/// LikeState(...).copyWith(id: 12, name: "My name")
/// ````
LikeState call({
List<String>? likedIds,
});
}
/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfLikeState.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfLikeState.copyWith.fieldName(...)`
class _$LikeStateCWProxyImpl implements _$LikeStateCWProxy {
final LikeState _value;
const _$LikeStateCWProxyImpl(this._value);
@override
LikeState likedIds(List<String>? likedIds) => this(likedIds: likedIds);
@override
/// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `LikeState(...).copyWith.fieldName(...)` to override fields one at a time with nullification support.
///
/// Usage
/// ```dart
/// LikeState(...).copyWith(id: 12, name: "My name")
/// ````
LikeState call({
Object? likedIds = const $CopyWithPlaceholder(),
}) {
return LikeState(
likedIds: likedIds == const $CopyWithPlaceholder()
? _value.likedIds
// ignore: cast_nullable_to_non_nullable
: likedIds as List<String>?,
);
}
}
extension $LikeStateCopyWith on LikeState {
/// Returns a callable class that can be used as follows: `instanceOfLikeState.copyWith(...)` or like so:`instanceOfLikeState.copyWith.fieldName(...)`.
// ignore: library_private_types_in_public_api
_$LikeStateCWProxy get copyWith => _$LikeStateCWProxyImpl(this);
}

View File

@ -5,23 +5,26 @@ packages:
dependency: transitive
description:
name: _fe_analyzer_shared
sha256: f256b0c0ba6c7577c15e2e4e114755640a875e885099367bf6e012b19314c834
sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a
url: "https://pub.dev"
source: hosted
version: "72.0.0"
_macros:
dependency: transitive
description: dart
source: sdk
version: "0.3.2"
version: "61.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
sha256: b652861553cd3990d8ed361f7979dc6d7053a9ac8843fa73820ab68ce5410139
sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562
url: "https://pub.dev"
source: hosted
version: "6.7.0"
version: "5.13.0"
archive:
dependency: transitive
description:
name: archive
sha256: "6199c74e3db4fbfbd04f66d739e72fe11c8a8957d5f219f1f4482dbde6420b5a"
url: "https://pub.dev"
source: hosted
version: "4.0.2"
args:
dependency: transitive
description:
@ -134,6 +137,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.3"
cli_util:
dependency: transitive
description:
name: cli_util
sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c
url: "https://pub.dev"
source: hosted
version: "0.4.2"
clock:
dependency: transitive
description:
@ -166,6 +177,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.1.2"
copy_with_extension:
dependency: transitive
description:
name: copy_with_extension
sha256: "9c17d2b9a041ad19c97aa544c46a60f192cd409529bb9cfb98f48f336bb84d31"
url: "https://pub.dev"
source: hosted
version: "4.0.4"
copy_with_extension_gen:
dependency: "direct main"
description:
name: copy_with_extension_gen
sha256: "19ab5e5095a9047315b42a6c2bb7ddf59a85cd23a75278500661ced4299165e9"
url: "https://pub.dev"
source: hosted
version: "4.0.4"
crypto:
dependency: transitive
description:
@ -186,10 +213,10 @@ packages:
dependency: transitive
description:
name: dart_style
sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab"
sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55"
url: "https://pub.dev"
source: hosted
version: "2.3.7"
version: "2.3.2"
dio:
dependency: "direct main"
description:
@ -222,6 +249,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:
@ -251,6 +286,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:
@ -259,11 +302,37 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.0.0"
flutter_localization:
dependency: "direct main"
description:
name: flutter_localization
sha256: "9b3b8825146a3850297a0ec3686b326d618328dca4cd5178b764af9303a26379"
url: "https://pub.dev"
source: hosted
version: "0.2.2"
flutter_localizations:
dependency: transitive
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:
@ -288,6 +357,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:
@ -304,6 +381,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.0.2"
image:
dependency: transitive
description:
name: image
sha256: "8346ad4b5173924b5ddddab782fc7d8a6300178c8b1dc427775405a01701c4a6"
url: "https://pub.dev"
source: hosted
version: "4.5.2"
intl:
dependency: "direct main"
description:
name: intl
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
url: "https://pub.dev"
source: hosted
version: "0.19.0"
io:
dependency: transitive
description:
@ -332,10 +425,10 @@ packages:
dependency: "direct dev"
description:
name: json_serializable
sha256: c2fcb3920cf2b6ae6845954186420fca40bc0a8abcc84903b7801f17d7050d7c
sha256: ea1432d167339ea9b5bb153f0571d0039607a873d6e04e0117af043f14a1fd4b
url: "https://pub.dev"
source: hosted
version: "6.9.0"
version: "6.8.0"
leak_tracker:
dependency: transitive
description:
@ -376,14 +469,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.0"
macros:
dependency: transitive
description:
name: macros
sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536"
url: "https://pub.dev"
source: hosted
version: "0.1.2-main.4"
matcher:
dependency: transitive
description:
@ -440,6 +525,62 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.9.0"
path_parsing:
dependency: transitive
description:
name: path_parsing
sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
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:
@ -448,6 +589,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:
@ -480,6 +629,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: "02a7d8a9ef346c9af715811b01fbd8e27845ad2c41148eefd31321471b41863d"
url: "https://pub.dev"
source: hosted
version: "2.4.0"
shared_preferences_foundation:
dependency: transitive
description:
name: shared_preferences_foundation
sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03"
url: "https://pub.dev"
source: hosted
version: "2.5.4"
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:
@ -589,6 +794,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.4.0"
vector_graphics:
dependency: transitive
description:
name: vector_graphics
sha256: "27d5fefe86fb9aace4a9f8375b56b3c292b64d8c04510df230f849850d912cb7"
url: "https://pub.dev"
source: hosted
version: "1.1.15"
vector_graphics_codec:
dependency: transitive
description:
name: vector_graphics_codec
sha256: "2430b973a4ca3c4dbc9999b62b8c719a160100dcbae5c819bae0cacce32c9cdb"
url: "https://pub.dev"
source: hosted
version: "1.1.12"
vector_graphics_compiler:
dependency: transitive
description:
name: vector_graphics_compiler
sha256: "1b4b9e706a10294258727674a340ae0d6e64a7231980f9f9a3d12e4b42407aad"
url: "https://pub.dev"
source: hosted
version: "1.1.16"
vector_math:
dependency: transitive
description:
@ -637,6 +866,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:
@ -647,4 +892,4 @@ packages:
version: "3.1.2"
sdks:
dart: ">=3.5.3 <4.0.0"
flutter: ">=3.18.0-18.0.pre.54"
flutter: ">=3.24.0"

View File

@ -1,101 +1,54 @@
name: flutter_labs_app
description: "A new Flutter project."
# The following line prevents the package from being accidentally published to
# pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# In Android, build-name is used as versionName while build-number used as versionCode.
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
version: 1.0.0+1
environment:
sdk: ^3.5.3
# Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions
# consider running `flutter pub upgrade --major-versions`. Alternatively,
# dependencies can be manually updated by changing the version numbers below to
# the latest version available on pub.dev. To see which dependencies have newer
# versions available, run `flutter pub outdated`.
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.8
json_annotation: ^4.9.0
dio: ^5.4.2+1
pretty_dio_logger: ^1.3.1
copy_with_extension_gen: ^4.0.0
#BLoC
equatable: ^2.0.5
flutter_bloc: ^8.1.5
flutter_localization:
intl: 0.19.0
shared_preferences: 2.2.3
flutter_svg: 2.0.7
dev_dependencies:
flutter_test:
sdk: flutter
#Иконки
flutter_launcher_icons: 0.13.1
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_icons:
android: "ic_launcher"
ios: true
image_path: "assets/launcher.jpg"
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.
generate: true
uses-material-design: true
# To add assets to your application, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/to/resolution-aware-images
# For details regarding adding assets from package dependencies, see
# https://flutter.dev/to/asset-from-package
# To add custom fonts to your application, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts from package dependencies,
# see https://flutter.dev/to/font-from-package
assets:
- assets/svg/

View File

@ -6,6 +6,9 @@
#include "generated_plugin_registrant.h"
#include <flutter_localization/flutter_localization_plugin_c_api.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
FlutterLocalizationPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FlutterLocalizationPluginCApi"));
}

View File

@ -3,6 +3,7 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
flutter_localization
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST