import 'package:card_app/components/extensions/context_x.dart'; import 'package:card_app/components/utils/debounce.dart'; import 'package:card_app/domain/models/card.dart'; import 'package:card_app/presentation/common/svg_objects.dart'; import 'package:card_app/presentation/home_page/bloc/bloc.dart'; import 'package:card_app/presentation/home_page/bloc/events.dart'; import 'package:card_app/presentation/like_bloc/know_bloc.dart'; import 'package:card_app/presentation/like_bloc/know_event.dart'; import 'package:card_app/presentation/locale_bloc/locale_events.dart'; import 'package:card_app/repositories/WordsRepository.dart'; import 'package:card_app/repositories/mock_repository.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../details_page/details_page.dart'; import '../like_bloc/know_state.dart'; import '../locale_bloc/locale_bloc.dart'; import '../locale_bloc/locale_state.dart'; import 'bloc/state.dart'; part 'card.dart'; class MyHomePage extends StatefulWidget { const MyHomePage({super.key, required this.title}); final String title; @override State createState() => _MyHomePageState(); } class _MyHomePageState extends State { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, title: Text(widget.title), ), body: Body()); } } class Body extends StatefulWidget { const Body({super.key}); @override _BodyState createState() => _BodyState(); } class _BodyState extends State { final SearchController searchController = SearchController(); final scrollController = ScrollController(); // Future?>? data; @override void initState() { SvgObjects.init(); WidgetsBinding.instance.addPostFrameCallback((_) { context.read().add(const HomeLoadDataEvent()); context.read().add(const LoadKnowsEvent()); }); scrollController.addListener(_onNextPageListener); super.initState(); //data = WordsRepository().loadData(); // Инициализация данных } void _onNextPageListener() { if (scrollController.offset > scrollController.position.maxScrollExtent - 300) { final bloc = context.read(); if (!bloc.state.isPaginationLoading) { 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 Padding( padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top), child: Column(children: [ Row( children: [ Expanded( flex: 4, child: Padding( padding: const EdgeInsets.all(12), child: CupertinoSearchTextField( placeholder: context.locale.search, onChanged: (search) { Debounce.run(() => context.read().add(HomeLoadDataEvent(search: search))); }, ), ), ), GestureDetector( onTap: () => context.read().add(const ChangeLocaleEvent()), child: SizedBox.square( dimension: 50, child: Padding( padding: const EdgeInsets.only(right: 12), child: BlocBuilder( builder: (context, state) { return state.currentLocale.languageCode == 'ru' ? const SvgRu() : const SvgUk(); }, ), ), ), ), ], ), BlocBuilder( builder: (context, state) => state.error != null ? Text(state.error ?? '', style: Theme.of(context).textTheme.headlineLarge?.copyWith(color: Colors.red)) : state.isLoading ? const CircularProgressIndicator() : BlocBuilder( builder: (context, knowState) { return 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, onKnow:_onKnow, isKnown: knowState.knownIds?.contains(data.id) == true, onTap: () => _navToDetails(context, data), ) : const SizedBox.shrink(); }, ), )); } ), ), BlocBuilder( builder: (context, state) => state.isPaginationLoading ? const CircularProgressIndicator() : const SizedBox.shrink(), ) ])); } void _navToDetails(BuildContext context, CardData data) { Navigator.push( context, CupertinoPageRoute(builder: (context) => DetailPage((data))), ); } void _showSnackBar(BuildContext context, String title, bool isKnow) { WidgetsBinding.instance.addPostFrameCallback((_) { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text( '${context.locale.start} ${isKnow ? context.locale.known : context.locale.unknown} ${context.locale.end} $title', style: Theme.of(context).textTheme.bodyLarge, ), backgroundColor: Colors.indigoAccent, duration: const Duration(seconds: 2), )); }); } Future _onRefresh() { context.read().add(HomeLoadDataEvent(search: searchController.text)); return Future.value(null); } void _onKnow(String? id, String title, bool isKnown){ if (id != null){ context.read().add(ChangeKnowEvent(id)); _showSnackBar(context, title, !isKnown); } } } // class _CardState extends State<_Card> { // bool isKnow = false; // // @override // Widget build(BuildContext context) { // return GestureDetector( // onTap: widget.onTap, // child: Container( // constraints: const BoxConstraints(minHeight: 140, maxWidth: 240), // padding: const EdgeInsets.all(20), // margin: const EdgeInsets.all(10), // decoration: BoxDecoration( // color: Colors.black12, // borderRadius: BorderRadius.circular(10), // ), // child: LayoutBuilder(builder: (context, constraints) { // double imageWidth = constraints.maxWidth; // { // return Stack( // children: [ // Column( // children: [ // Column( // children: [ // Image.network(widget.image, width: 300), // Text( // widget.word, // style: Theme.of(context).textTheme.headlineLarge, // ), // Text( // widget.translation, // style: Theme.of(context).textTheme.bodyMedium, // ), // ], // ), // Align( // alignment: Alignment.bottomRight, // child: Padding( // padding: const EdgeInsets.only(left: 8.0), // child: GestureDetector( // onTap: () => onKnow?.call(id, text, isKnown), // child: AnimatedSwitcher( // duration: const Duration(milliseconds: 200), // child: isKnow // ? const Icon(Icons.check_circle, // color: Colors.green, key: ValueKey(0)) // : const Icon(Icons.check_circle_outline, key: ValueKey(1)), // ), // ), // ), // ), // ], // ), // Align( // alignment: Alignment.center, // ) // ], // ); // } // })), // ); // } // }