|
|
import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:repositories/app_api_domain/models/post_model.dart'; import 'package:sonnat/core/extensions/context_extension.dart'; import 'package:sonnat/core/extensions/string_extension.dart'; import 'package:sonnat/core/language/translator.dart'; import 'package:sonnat/core/select_language/cubit/select_language_cubit.dart'; import 'package:sonnat/core/select_language/screen/select_language_screen.dart'; import 'package:sonnat/core/utils/app_constants.dart'; import 'package:sonnat/core/utils/base_cubit_type.dart'; import 'package:sonnat/core/utils/initializer.dart'; import 'package:sonnat/core/widgets/loading_list_widget.dart'; import 'package:sonnat/core/widgets/more_options_widget.dart'; import 'package:sonnat/features/about_us/about_us_screen.dart'; import 'package:sonnat/features/posts/cubit/posts_cubit.dart'; import 'package:sonnat/features/posts/widgets/filter_item_widget.dart'; import 'package:sonnat/features/posts/widgets/post_item_widget.dart'; import 'package:sonnat/features/posts/widgets/search_widget.dart'; import 'package:sonnat/features/single_post/cubit/single_post_cubit.dart'; import 'package:sonnat/features/single_post/screen/single_post_screen.dart';
class PostsScreen extends StatefulWidget { final String title; final bool searchMode; final bool showFilters;
const PostsScreen({ super.key, required this.title, this.searchMode = false, this.showFilters = false, });
@override State<PostsScreen> createState() => _PostsScreenState(); }
class _PostsScreenState extends State<PostsScreen> { late final PostsCubit _cubit; bool _loading = true; bool _getListFlag = false; late bool _searchMode; final ScrollController _controller = ScrollController(); int _selectedFilterIndex = -1;
final List<FilterItem> _filterList = [ const FilterItem(selected: false, title: 'ابوبکر', catId: '77'), const FilterItem(selected: true, title: 'عمر', catId: '78'), const FilterItem(selected: false, title: 'عثمان', catId: '79'), ];
@override void initState() { _searchMode = widget.searchMode; _cubit = BlocProvider.of<PostsCubit>(context); _cubit.getData(catId: _cubit.lastCatId); _controller.addListener(_onScroll); super.initState(); }
void _onScroll() { final double maxScroll = _controller.position.maxScrollExtent; final double currentScroll = _controller.position.pixels; if (maxScroll - currentScroll <= 400) { if (_getListFlag) { _getListFlag = false; _cubit.getData(catId: _cubit.lastCatId); } } }
@override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: BlocBuilder<PostsCubit, BaseCubitType<PostsState>>( builder: (context, state) { switch (state.eventName!) { case PostsState.empty: break; case PostsState.data: _loading = false; _getListFlag = true; break; case PostsState.loading: _loading = true; break; case PostsState.loadingPagination: break; case PostsState.changeFilterIndex: _selectedFilterIndex = state.data; _controller.jumpTo(0); _loading = true; break; } return CustomScrollView( controller: _controller, slivers: [ SliverAppBar( floating: true, elevation: 0, backgroundColor: const Color(0xffE7E7F5), automaticallyImplyLeading: false, forceElevated: false, shadowColor: Colors.transparent, bottom: PreferredSize( preferredSize: const Size.fromHeight(116), child: Column( children: [ SizedBox(height: context.height * 26 / AppConstants.instance.appHeight), Padding( padding: EdgeInsets.symmetric( horizontal: context.width * 26 / AppConstants.instance.appWidth, ), child: _searchMode ? Row( children: [ Expanded( child: SearchWidget( search: (query) { _cubit.search(query: query); }, ), ), SizedBox(width: context.width * 12 / AppConstants.instance.appWidth), GestureDetector( onTap: () { _cubit.clearSearch(); setState(() { _searchMode = !_searchMode; }); }, child: SvgPicture.asset( 'ic_back'.svgPath, ), ), ], ) : Stack( children: [ Align( alignment: AlignmentDirectional.centerStart, child: GestureDetector( onTap: _showOptions, child: SvgPicture.asset('ic_more'.svgPath), ), ), PositionedDirectional( start: context.width * 44 / AppConstants.instance.appWidth, child: GestureDetector( onTap: () { setState(() { _searchMode = !_searchMode; }); }, child: SvgPicture.asset('ic_rounded_search'.svgPath), ), ), Align( alignment: AlignmentDirectional.center, child: Padding( padding: const EdgeInsets.only(top: 8), child: Text( widget.title, style: const TextStyle( color: Color(0xff404966), fontSize: 22, ), ), ), ), Align( alignment: AlignmentDirectional.centerEnd, child: GestureDetector( onTap: () { Navigator.pop(context); }, child: RotatedBox( quarterTurns: Initializer.instance.getTextDirection() == TextDirection.ltr ? 90 : 0, child: SvgPicture.asset('ic_back'.svgPath), ), ), ), ], ), ), if (_searchMode) Padding( padding: EdgeInsets.only( top: context.height * 17 / AppConstants.instance.appHeight, left: context.width * 26 / AppConstants.instance.appWidth, right: context.width * 26 / AppConstants.instance.appWidth, ), child: Row( children: [ SvgPicture.asset( 'ic_search'.svgPath, colorFilter: const ColorFilter.mode( Color(0xff26237A), BlendMode.srcIn, ), ), const SizedBox(width: 8), Text( '${Translator.translate('search')}:', style: const TextStyle( color: Color(0xff26237A), fontSize: 16, ), ), const SizedBox(width: 8), Expanded( child: Text( _cubit.query, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle( color: Color(0xff26237A), fontSize: 16, ), ), ), const Spacer(), Text( _loading ? 'در حال جستجو' : _cubit.query.isEmpty ? '' : _cubit.searchedList.isEmpty ? 'موردی یافت نشد' : '${_cubit.searchedList.length} مورد یافت شد', style: const TextStyle( color: Color(0xff636E88), fontSize: 12, ), ) ], ), ), SizedBox(height: context.height * 35 / AppConstants.instance.appHeight), if (widget.showFilters) SizedBox( height: context.height * 31 / AppConstants.instance.appHeight, child: ListView.builder( padding: EdgeInsetsDirectional.only( start: context.width * 26 / AppConstants.instance.appWidth, ), itemBuilder: (context, index) { return GestureDetector( onTap: () { _cubit.changeFilter(index, _filterList[index].catId); }, child: FilterItemWidget( title: _filterList[index].title, selected: index == _selectedFilterIndex, ), ); }, itemCount: _filterList.length, scrollDirection: Axis.horizontal, ), ), SizedBox(height: context.height * 26 / AppConstants.instance.appHeight), ], ), ), ), SliverList( delegate: SliverChildBuilderDelegate( (context, index) { if (_loading) { return const LoadingListWidget(); } return ListView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemBuilder: (context, index) { if (_searchMode) { return GestureDetector( onTap: () => _clickOnPost(_cubit.searchedList[index]), child: PostItemWidget(post: _cubit.searchedList[index]), ); } return GestureDetector( onTap: () => _clickOnPost(_cubit.postList[index]), child: PostItemWidget(post: _cubit.postList[index]), ); }, itemCount: _searchMode ? _cubit.searchedList.length : _cubit.postList.length, ); }, childCount: 1, ), ), ], ); }, ), ), ); }
void _clickOnPost(PostModel post) { Navigator.push( context, MaterialPageRoute( builder: (context) { return BlocProvider( child: SinglePostScreen(postId: post.id), create: (context) => SinglePostCubit(), ); }, ), ); }
void _showOptions() { showModalBottomSheet( context: context, backgroundColor: Colors.transparent, builder: (context) { return Container( height: 120, width: context.width, decoration: BoxDecoration( color: Colors.white, border: Border.all(color: Colors.white, width: 0.2), borderRadius: const BorderRadius.only( topLeft: Radius.circular(16), topRight: Radius.circular(16), ), ), padding: const EdgeInsets.only( top: 16, left: 4, right: 4, ), child: Column( children: [ MoreOptionsWidget( title: Translator.translate('about_us'), onTap: () { Navigator.pop(context); Navigator.push( context, MaterialPageRoute( builder: (context) { return const AboutUsScreen(); }, ), ); }, ), const SizedBox(height: 8), Container( width: context.width, height: 1, color: const Color(0xffD3D8E9), ), const SizedBox(height: 8), MoreOptionsWidget( title: Translator.translate('select_language'), onTap: () { Navigator.pop(context); Navigator.push( context, MaterialPageRoute( builder: (context) { return BlocProvider( child: const SelectLanguageScreen(), create: (context) => SelectLanguageCubit(), ); }, ), ); }, ), ], ), ); }, ); } }
class FilterItem { final bool selected; final String title; final String catId;
const FilterItem({required this.selected, required this.title, required this.catId}); }
|