125 lines
3.4 KiB
Dart
125 lines
3.4 KiB
Dart
|
import 'package:flutter/material.dart';
|
||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||
|
import 'package:test_app/domain/card.dart';
|
||
|
import 'package:test_app/utils/debounce.dart';
|
||
|
import 'package:test_app/view/details_page/details_page.dart';
|
||
|
import 'package:test_app/view/home_page/bloc/bloc.dart';
|
||
|
import 'package:test_app/view/home_page/bloc/events.dart';
|
||
|
import 'package:test_app/view/home_page/bloc/state.dart';
|
||
|
import 'package:test_app/view/home_page/card/home_card.dart';
|
||
|
import 'package:test_app/view/home_page/like_bloc/like_bloc.dart';
|
||
|
import 'package:test_app/view/home_page/like_bloc/like_event.dart';
|
||
|
|
||
|
part 'home_page_error.dart';
|
||
|
part 'home_page_list.dart';
|
||
|
part 'home_page_spinner.dart';
|
||
|
|
||
|
class MyHomePage extends StatefulWidget {
|
||
|
const MyHomePage({super.key, required this.title});
|
||
|
|
||
|
final String title;
|
||
|
|
||
|
@override
|
||
|
State<MyHomePage> createState() => _MyHomePageState();
|
||
|
}
|
||
|
|
||
|
class _MyHomePageState extends State<MyHomePage> {
|
||
|
final Color _color = Colors.orangeAccent;
|
||
|
|
||
|
@override
|
||
|
Widget build(BuildContext context) {
|
||
|
return Scaffold(
|
||
|
appBar: AppBar(
|
||
|
backgroundColor: _color,
|
||
|
title: Text(widget.title),
|
||
|
),
|
||
|
body: const Body(),
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class Body extends StatefulWidget {
|
||
|
const Body({super.key});
|
||
|
|
||
|
@override
|
||
|
State<Body> createState() => _BodyState();
|
||
|
}
|
||
|
|
||
|
class _BodyState extends State<Body> {
|
||
|
final searchController = TextEditingController();
|
||
|
final scrollController = ScrollController();
|
||
|
|
||
|
@override
|
||
|
void initState() {
|
||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||
|
context.read<HomeBloc>().add(const HomeLoadDataEvent());
|
||
|
context.read<LikeBloc>().add(const LoadLikesEvent());
|
||
|
});
|
||
|
scrollController.addListener(_onNextPageListener);
|
||
|
super.initState();
|
||
|
}
|
||
|
|
||
|
void _onNextPageListener() {
|
||
|
Debounce.run(() {
|
||
|
if (scrollController.offset >
|
||
|
scrollController.position.maxScrollExtent - 10) {
|
||
|
final bloc = context.read<HomeBloc>();
|
||
|
if (!bloc.state.isLoading) {
|
||
|
bloc.add(HomeLoadDataEvent(
|
||
|
search: searchController.text,
|
||
|
nextPage: bloc.state.data?.nextPage));
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
void dispose() {
|
||
|
searchController.dispose();
|
||
|
scrollController.dispose();
|
||
|
super.dispose();
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
Widget build(BuildContext context) {
|
||
|
return Column(
|
||
|
children: [
|
||
|
Padding(
|
||
|
padding: const EdgeInsets.all(16),
|
||
|
child: SearchBar(
|
||
|
leading: const Icon(Icons.search),
|
||
|
trailing: [
|
||
|
IconButton(
|
||
|
onPressed: () {
|
||
|
searchController.clear();
|
||
|
context.read<HomeBloc>().add(const HomeLoadDataEvent());
|
||
|
},
|
||
|
icon: const Icon(Icons.clear)),
|
||
|
],
|
||
|
controller: searchController,
|
||
|
onChanged: (search) {
|
||
|
Debounce.run(() => context
|
||
|
.read<HomeBloc>()
|
||
|
.add(HomeLoadDataEvent(search: search)));
|
||
|
},
|
||
|
),
|
||
|
),
|
||
|
Expanded(
|
||
|
child: Stack(
|
||
|
children: [
|
||
|
const _HomePageError(),
|
||
|
Positioned.fill(
|
||
|
child: _HomePageList(
|
||
|
searchController: searchController,
|
||
|
scrollController: scrollController,
|
||
|
),
|
||
|
),
|
||
|
const _HomePageSpinner(),
|
||
|
],
|
||
|
),
|
||
|
),
|
||
|
],
|
||
|
);
|
||
|
}
|
||
|
}
|