ура 1 этап работает, спааать

This commit is contained in:
Timourka 2024-10-27 01:34:35 +04:00
parent ce3ed67612
commit 192c7f6472
8 changed files with 175 additions and 60 deletions

View File

@ -1,6 +1,10 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:laba1/presentation/home_page/bloc/bloc.dart';
import 'package:laba1/presentation/home_page/home_page.dart';
import 'data/repositories/potter_repository.dart';
void main() {
runApp(const MyApp());
}
@ -15,7 +19,15 @@ class MyApp extends StatelessWidget {
theme: ThemeData(
primarySwatch: Colors.amber,
),
home: const MyHomePage(title: 'Кувшинов Тимур Александрович'),
home: RepositoryProvider<PotterRepository>(
lazy: true,
create: (_) => PotterRepository(),
child: BlocProvider<HomeBloc>(
lazy: false,
create: (context) => HomeBloc(context.read<PotterRepository>()),
child: const MyHomePage(title: 'Кувшинов Тимур Александрович'),
),
),
);
}
}

View File

@ -0,0 +1,16 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:laba1/data/repositories/mock_repository.dart';
import 'package:laba1/presentation/home_page/bloc/state.dart';
import '../../../data/repositories/potter_repository.dart';
import 'events.dart';
class HomeBloc extends Bloc<HomeEvent, HomeState> {
final PotterRepository repo;
HomeBloc(this.repo) : super(const HomeState()) {
on<HomeLoadDataEvent>(_onLoadData);
}
void _onLoadData(HomeLoadDataEvent event, Emitter<HomeState> emit) {
emit(state.copyWith(data: repo.loadData()));
}
}

View File

@ -0,0 +1,6 @@
abstract class HomeEvent {
const HomeEvent();
}
class HomeLoadDataEvent extends HomeEvent {
const HomeLoadDataEvent();
}

View File

@ -0,0 +1,11 @@
import 'package:equatable/equatable.dart';
import '../../../domain/models/card.dart';
class HomeState extends Equatable {
final Future<List<CardData>?>? data;
const HomeState({this.data});
HomeState copyWith({Future<List<CardData>?>? data}) => HomeState(data: data ?? this.data);
@override
List<Object?> get props => [data];
}

View File

@ -1,6 +1,6 @@
part of 'home_page.dart';
typedef OnLikeCallback = void Function(bool isLiked)?;
typedef OnLikeCallback = void Function(String title, bool isLiked)?;
class _Card extends StatefulWidget {
final String _text;
@ -100,7 +100,7 @@ class _CardState extends State<_Card> {
onTap: () {
isLiked = !isLiked;
setState(() {});
widget.onLike?.call(isLiked);
widget.onLike?.call(widget._text, isLiked);
},
child: AnimatedSwitcher(
duration: const Duration(milliseconds: 100),

View File

@ -1,62 +1,74 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:laba1/data/repositories/potter_repository.dart';
import 'package:laba1/presentation/details_page/details_page.dart';
import '../../data/repositories/mock_repository.dart';
import '../../domain/models/card.dart';
import '../dialogs/show_dialog.dart';
import 'bloc/bloc.dart';
import 'bloc/events.dart';
import 'bloc/state.dart';
part 'card.dart';
class MyHomePage extends StatelessWidget {
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
title: Text(widget.title),
backgroundColor: Colors.amber,
),
backgroundColor: Colors.yellow,
body: const Body());
body: const _Body());
}
}
class Body extends StatefulWidget {
const Body({Key? key}) : super(key: key);
class _Body extends StatefulWidget {
const _Body({Key? key}) : super(key: key);
@override
State<Body> createState() => _BodyState();
State<_Body> createState() => _BodyState();
}
class _BodyState extends State<Body> {
class _BodyState extends State<_Body> {
final searchController = TextEditingController();
late Future<List<CardData>?> data;
final repo = PotterRepository();
bool isLoading = false;
@override
void initState() {
data = repo.loadData(onError: (e) => showErrorDialog(context, error: e));
isLoading = true;
data.then((_) => setState(() {
isLoading = false; // Остановить индикатор при завершении загрузки
}));
WidgetsBinding.instance.addPostFrameCallback((_) {
context.read<HomeBloc>().add(const HomeLoadDataEvent());
});
super.initState();
}
@override
void dispose() {
searchController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Center(
child: Stack(
children: [
Positioned.fill(
child: FutureBuilder<List<CardData>?>(
future: data,
Positioned.fill(
child: BlocBuilder<HomeBloc, HomeState > (
builder: (context, state) =>
FutureBuilder<List<CardData>?>(
future: state.data,
builder: (context, snapshot) {
var cards = Column(
children: [],
@ -73,53 +85,42 @@ class _BodyState extends State<Body> {
));
cards.children.addAll(
snapshot.data
?.map((e) => _Card.fromData(
e,
onLike: (bool isLiked) {
_showSnackBar(context, isLiked);
},
onTap: () => _navToDetails(context, e),
))
.toList() ??
?.map((e) =>
_Card.fromData(
e,
onLike: (String title, bool isLiked) {
_showSnackBar(context, title, isLiked);
},
onTap: () => _navToDetails(context, e),
))
.toList() ??
[],
);
return !isLoading
return snapshot.hasData
? SingleChildScrollView(
child: cards,
)
: Center(child: CircularProgressIndicator());
},
),
),
Align(
alignment: Alignment.topCenter,
child: Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8),
child: CupertinoSearchTextField(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(20),
bottomRight: Radius.circular(20),
),
backgroundColor: Colors.amberAccent,
controller: searchController,
onChanged: (search) {
setState(() {
isLoading = true;
});
setState(() {
data = repo.loadData(
q: search,
onError: (e) => showErrorDialog(context, error: e),
);
data.then((_) => setState(() {
isLoading =
false; // Остановить индикатор при завершении загрузки
}));
});
},
),),
Align(
alignment: Alignment.topCenter,
child: Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8),
child: CupertinoSearchTextField(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(20),
bottomRight: Radius.circular(20),
),
backgroundColor: Colors.amberAccent,
controller: searchController,
onChanged: (search) {
//TODO
},
),
),
),
],
),
);
@ -132,12 +133,15 @@ class _BodyState extends State<Body> {
);
}
void _showSnackBar(BuildContext context, bool isLiked) {
void _showSnackBar(BuildContext context, String title, bool isLiked) {
WidgetsBinding.instance.addPostFrameCallback((_) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(
'Card ${isLiked ? 'liked' : 'unliked'}',
style: Theme.of(context).textTheme.bodyLarge,
'$title ${isLiked ? 'liked' : 'unliked'}',
style: Theme
.of(context)
.textTheme
.bodyLarge,
),
backgroundColor: Colors.orangeAccent,
duration: const Duration(seconds: 1),

View File

@ -38,6 +38,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.11.0"
bloc:
dependency: transitive
description:
name: bloc
sha256: "106842ad6569f0b60297619e9e0b1885c2fb9bf84812935490e6c5275777804e"
url: "https://pub.dev"
source: hosted
version: "8.1.4"
boolean_selector:
dependency: transitive
description:
@ -158,6 +166,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.1.1"
copy_with_extension:
dependency: transitive
description:
name: copy_with_extension
sha256: fbcf890b0c34aedf0894f91a11a579994b61b4e04080204656b582708b5b1125
url: "https://pub.dev"
source: hosted
version: "5.0.4"
copy_with_extension_gen:
dependency: "direct main"
description:
name: copy_with_extension_gen
sha256: "51cd11094096d40824c8da629ca7f16f3b7cea5fc44132b679617483d43346b0"
url: "https://pub.dev"
source: hosted
version: "5.0.4"
crypto:
dependency: transitive
description:
@ -198,6 +222,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.0"
equatable:
dependency: "direct main"
description:
name: equatable
sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2
url: "https://pub.dev"
source: hosted
version: "2.0.5"
fake_async:
dependency: transitive
description:
@ -227,6 +259,14 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_bloc:
dependency: "direct main"
description:
name: flutter_bloc
sha256: b594505eac31a0518bdcb4b5b79573b8d9117b193cc80cc12e17d639b10aa27a
url: "https://pub.dev"
source: hosted
version: "8.1.6"
flutter_lints:
dependency: "direct dev"
description:
@ -392,6 +432,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.0"
nested:
dependency: transitive
description:
name: nested
sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
package_config:
dependency: transitive
description:
@ -424,6 +472,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.4.0"
provider:
dependency: transitive
description:
name: provider
sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c
url: "https://pub.dev"
source: hosted
version: "6.1.2"
pub_semver:
dependency: transitive
description:

View File

@ -36,15 +36,25 @@ dependencies:
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
# Сетевое взаимодействие
json_annotation: ^4.8.1
dio: ^5.4.2+1
pretty_dio_logger: ^1.3.1
# BLoC
equatable: ^2.0.5
flutter_bloc: ^8.1.5
copy_with_extension_gen: ^5.0.4
dev_dependencies:
flutter_test:
sdk: flutter
# Сетевое взаимодействие
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