end lab6, but not end lection 6

This commit is contained in:
revengel66 2024-11-28 15:46:10 +04:00
parent efbed7104a
commit aa0c4a7f9d
6 changed files with 137 additions and 27 deletions

View File

@ -0,0 +1,18 @@
import 'dart:async';
import 'dart:ui';
class Debounce {
factory Debounce() => _instance;
Debounce._();
static final Debounce _instance = Debounce._();
static Timer? _timer;
static void run(
VoidCallback action, {
Duration delay = const Duration(milliseconds: 500),
}) {
_timer?.cancel();
_timer = Timer(delay, action);
}
}

View File

@ -1,5 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:pmd_lab/presentation/home_page/bloc/bloc.dart';
import 'package:pmd_lab/presentation/home_page/home_page.dart';
import 'package:pmd_lab/repositories/potter_repository.dart';
void main() {
runApp(const MyApp());
@ -16,7 +19,15 @@ class MyApp extends StatelessWidget {
// colorScheme: ColorScheme.fromSeed(seedColor: Colors.black), colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter rocks!'),
home: RepositoryProvider<PotterRepository>(
lazy: true,
create: (_) => PotterRepository(),
child: BlocProvider<HomeBloc>(
lazy: true,
create: (context) => HomeBloc(context.read<PotterRepository>()),
child: const MyHomePage(title: 'Potter API'),
),
)
);
}
}

View File

@ -0,0 +1,25 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:pmd_lab/presentation/home_page/bloc/events.dart';
import 'package:pmd_lab/presentation/home_page/bloc/state.dart';
import 'package:pmd_lab/repositories/potter_repository.dart';
class HomeBloc extends Bloc<HomeEvent, HomeState> {
final PotterRepository repo;
HomeBloc(this.repo) : super(const HomeState()) {
on<HomeLoadDataEvent>(_onLoadData);
}
Future<void> _onLoadData(HomeLoadDataEvent event, Emitter<HomeState> emit) async {
emit(state.copyWith(isLoading: true));
final data = await repo.loadData(q: event.search);
emit(state.copyWith(
isLoading: false,
data: data,
));
}
}

View File

@ -0,0 +1,9 @@
class HomeEvent {
const HomeEvent();
}
class HomeLoadDataEvent extends HomeEvent{
final String? search;
const HomeLoadDataEvent({this.search});
}

View File

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

View File

@ -1,7 +1,12 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:pmd_lab/components/utils/debounce.dart';
import 'package:pmd_lab/domain/models/card.dart';
import 'package:pmd_lab/presentation/details_page/details_page.dart';
import 'package:pmd_lab/presentation/home_page/bloc/bloc.dart';
import 'package:pmd_lab/presentation/home_page/bloc/events.dart';
import 'package:pmd_lab/presentation/home_page/bloc/state.dart';
import 'package:pmd_lab/repositories/api_interface.dart';
import 'package:pmd_lab/repositories/mock_repository.dart';
import 'package:pmd_lab/repositories/potter_repository.dart';
@ -80,8 +85,16 @@ class _BodyState extends State<Body> {
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) {
context.read<HomeBloc>().add(const HomeLoadDataEvent());
});
super.initState();
data = repo.loadData(q: null);
}
@override
void dispose(){
searchController.dispose();
super.dispose();
}
@override
@ -96,35 +109,35 @@ class _BodyState extends State<Body> {
child: CupertinoSearchTextField(
controller: searchController,
onChanged: (search) {
setState(() {
data = repo.loadData(q: search.isNotEmpty ? search : null);
});
Debounce.run(() => context.read<HomeBloc>().add(HomeLoadDataEvent(search: search)));
},
),
),
Expanded(
child: FutureBuilder<List<CardData>?>(
future: data,
builder: (context, snapshot) =>
SingleChildScrollView(
padding: const EdgeInsets.only(
left: 20, right: 20, top: 20),
child: snapshot.hasData
? Column(
children: snapshot.data?.map((data) {
return _Card.fromData(
data,
onLike: (text, isLiked) =>
_showSnackBar(context, text, isLiked),
onTap: () => _navToDetails(context, data),
);
}).toList() ??
[],
BlocBuilder<HomeBloc, HomeState>(
builder: (context, state) => state.isLoading
? const CircularProgressIndicator()
: Expanded(
child: RefreshIndicator(
onRefresh: _onRefresh,
child: ListView.builder(
padding: EdgeInsets.zero,
itemCount: state.data?.length ?? 0,
itemBuilder: (context, index) {
final data = state.data?[index];
return data != null
? _Card.fromData(
data,
onLike: (title, isLiked) => _showSnackBar(context, title, isLiked),
onTap: () => _navToDetails(context, data),
)
: const CircularProgressIndicator()
),
)
)
: const SizedBox.shrink();
},
), // ListView.builder
), // RefreshIndicator
), // Expanded
), // BlocBuilder
],
),
);
@ -152,5 +165,9 @@ class _BodyState extends State<Body> {
);
}
Future<void> _onRefresh() {
context.read<HomeBloc>().add(HomeLoadDataEvent(search: searchController.text));
return Future.value(null);
}
}