diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 046b655..6236380 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -2,7 +2,7 @@ > { Future _initial() async { String? language = _repository.getCurrentLanguage(); if (language == null || language == '') { - await Translator.setNewLanguage(Languages.fa); - emit(BaseCubitType(eventName: LanguageState.loaded, data: CurrentLanguage.fa)); + emit(BaseCubitType(eventName: LanguageState.notSet)); return; } switch (language) { @@ -56,12 +56,6 @@ class LanguageCubit extends Cubit> { } Future changeLanguage() async { - if (getCurrentLanguage() == 'fa') { - await Translator.setNewLanguage(Languages.en); - emit(BaseCubitType(eventName: LanguageState.loaded, data: CurrentLanguage.en)); - } else { - await Translator.setNewLanguage(Languages.fa); - emit(BaseCubitType(eventName: LanguageState.loaded, data: CurrentLanguage.fa)); - } + emit(BaseCubitType(eventName: LanguageState.loaded)); } } diff --git a/lib/core/select_language/cubit/select_language_cubit.dart b/lib/core/select_language/cubit/select_language_cubit.dart new file mode 100644 index 0000000..ff47916 --- /dev/null +++ b/lib/core/select_language/cubit/select_language_cubit.dart @@ -0,0 +1,34 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:sonnat/core/language/language_cubit.dart'; +import 'package:sonnat/core/language/languages.dart'; +import 'package:sonnat/core/language/translator.dart'; +import 'package:sonnat/core/utils/base_cubit_type.dart'; + +class SelectLanguageCubit extends Cubit> { + + SelectLanguageCubit() : super(BaseCubitType(eventName: SelectLanguageState.empty)); + + void empty() => emit(BaseCubitType(eventName: SelectLanguageState.empty)); + + Future selectLanguage(String language) async { + switch (language) { + case 'fa': + await Translator.setNewLanguage(Languages.fa); + emit(BaseCubitType(eventName: SelectLanguageState.loaded, data: CurrentLanguage.fa)); + return; + case 'en': + await Translator.setNewLanguage(Languages.en); + emit(BaseCubitType(eventName: SelectLanguageState.loaded, data: CurrentLanguage.en)); + return; + case 'ar': + await Translator.setNewLanguage(Languages.ar); + emit(BaseCubitType(eventName: SelectLanguageState.loaded, data: CurrentLanguage.ar)); + return; + } + } +} + +enum SelectLanguageState { + empty, + loaded, +} diff --git a/lib/core/select_language/screen/select_language_screen.dart b/lib/core/select_language/screen/select_language_screen.dart new file mode 100644 index 0000000..1f179e9 --- /dev/null +++ b/lib/core/select_language/screen/select_language_screen.dart @@ -0,0 +1,132 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:sonnat/core/extensions/context_extension.dart'; +import 'package:sonnat/core/extensions/string_extension.dart'; +import 'package:sonnat/core/language/language_cubit.dart'; +import 'package:sonnat/core/select_language/cubit/select_language_cubit.dart'; +import 'package:sonnat/core/utils/base_cubit_type.dart'; +import 'package:sonnat/features/main/main_screen.dart'; + +class SelectLanguageScreen extends StatefulWidget { + const SelectLanguageScreen({super.key}); + + @override + State createState() => _SelectLanguageScreenState(); +} + +class _SelectLanguageScreenState extends State { + late final SelectLanguageCubit _cubit; + + @override + void initState() { + _cubit = BlocProvider.of(context); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: const Color(0xff26237A), + body: SafeArea( + child: BlocBuilder>( + builder: (context, state) { + switch (state.eventName!) { + case SelectLanguageState.empty: + break; + case SelectLanguageState.loaded: + WidgetsBinding.instance.addPostFrameCallback((timeStamp) { + BlocProvider.of(context).changeLanguage(); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) { + return const MainScreen(); + }, + ), + ); + }); + break; + } + return Column( + children: [ + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + 'ic_select_language'.pngPath, + width: 72, + height: 36, + ), + const SizedBox(height: 15), + const Text( + 'Select Your Language', + style: TextStyle( + color: Color(0xffDEDEDE), + fontSize: 16, + fontFamily: 'Cairo', + ), + ), + ], + ), + ), + GestureDetector( + child: const SelectLanguageButtonWidget(title: 'English'), + onTap: () { + _cubit.selectLanguage('en'); + }, + ), + GestureDetector( + child: const SelectLanguageButtonWidget(title: 'العربیه'), + onTap: () { + _cubit.selectLanguage('fa'); + }, + ), + GestureDetector( + child: const SelectLanguageButtonWidget(title: 'فارسی'), + onTap: () { + _cubit.selectLanguage('fa'); + }, + ), + GestureDetector( + child: const SelectLanguageButtonWidget(title: 'اردو'), + onTap: () { + _cubit.selectLanguage('fa'); + }, + ), + const SizedBox(height: 30), + ], + ); + }, + ), + ), + ); + } +} + +class SelectLanguageButtonWidget extends StatelessWidget { + final String title; + + const SelectLanguageButtonWidget({super.key, required this.title}); + + @override + Widget build(BuildContext context) { + return Container( + width: context.width, + decoration: BoxDecoration( + color: const Color(0xff3733A1), + borderRadius: BorderRadius.circular(22), + ), + alignment: Alignment.center, + padding: const EdgeInsets.symmetric(vertical: 14), + margin: const EdgeInsets.symmetric(vertical: 7.5, horizontal: 40), + child: Text( + title, + style: const TextStyle( + color: Color(0xffffffff), + fontSize: 16, + ), + ), + ); + } +} diff --git a/lib/core/utils/app_utils.dart b/lib/core/utils/app_utils.dart index 44accaa..dea4130 100644 --- a/lib/core/utils/app_utils.dart +++ b/lib/core/utils/app_utils.dart @@ -63,26 +63,12 @@ class Utils { return '${jalali.year}/${jalali.month}/${jalali.day}'; } - ThemeData getAppTheme(BuildContext context, CurrentLanguage language) { - switch (language) { - case CurrentLanguage.en: - return ThemeData( - scaffoldBackgroundColor: const Color(0xffE7E7F5), - useMaterial3: true, - ); - case CurrentLanguage.fa: - return ThemeData( - fontFamily: 'Vazir', - scaffoldBackgroundColor: const Color(0xffE7E7F5), - useMaterial3: true, - ); - case CurrentLanguage.ar: - return ThemeData( - fontFamily: 'Cairo', - useMaterial3: true, - scaffoldBackgroundColor: const Color(0xffE7E7F5), - ); - } + ThemeData getAppTheme(BuildContext context) { + return ThemeData( + fontFamily: 'Vazir', + scaffoldBackgroundColor: const Color(0xffE7E7F5), + useMaterial3: true, + ); } EdgeInsets allMargin(num? num) { diff --git a/lib/core/widgets/loading_list_widget.dart b/lib/core/widgets/loading_list_widget.dart index 315f4d8..fb3d3a8 100644 --- a/lib/core/widgets/loading_list_widget.dart +++ b/lib/core/widgets/loading_list_widget.dart @@ -1,35 +1,30 @@ import 'package:flutter/material.dart'; import 'package:sonnat/core/extensions/context_extension.dart'; import 'package:sonnat/core/utils/app_constants.dart'; -import 'package:sonnat/core/widgets/shimmer.dart'; class LoadingListWidget extends StatelessWidget { const LoadingListWidget({super.key}); @override Widget build(BuildContext context) { - return Shimmer.fromColors( - baseColor: Colors.black12, - highlightColor: Colors.white, - child: ListView.builder( - padding: EdgeInsets.zero, - itemBuilder: (_, __) => Container( - height: 200, - decoration: BoxDecoration( - color: const Color(0xffffffff), - borderRadius: BorderRadius.circular(16), - ), - margin: EdgeInsets.only( - left: context.width * 26 / AppConstants.instance.appWidth, - right: context.width * 26 / AppConstants.instance.appWidth, - bottom: context.height * 8 / AppConstants.instance.appHeight, - top: context.height * 8 / AppConstants.instance.appHeight, - ), + return ListView.builder( + padding: EdgeInsets.zero, + itemBuilder: (_, __) => Container( + height: 340, + decoration: BoxDecoration( + color: Colors.grey, + borderRadius: BorderRadius.circular(16), + ), + margin: EdgeInsets.only( + left: context.width * 26 / AppConstants.instance.appWidth, + right: context.width * 26 / AppConstants.instance.appWidth, + bottom: context.height * 8 / AppConstants.instance.appHeight, + top: context.height * 8 / AppConstants.instance.appHeight, ), - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemCount: 10, ), + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemCount: 10, ); } } diff --git a/lib/features/aabout_us/about_us_screen.dart b/lib/features/aabout_us/about_us_screen.dart index 3cb5961..ab037b4 100644 --- a/lib/features/aabout_us/about_us_screen.dart +++ b/lib/features/aabout_us/about_us_screen.dart @@ -22,148 +22,157 @@ class _AboutUsScreenState extends State { return Scaffold( body: Padding( padding: EdgeInsets.symmetric(horizontal: context.width * 25 / AppConstants.instance.appWidth), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox(height: context.height * 33 / AppConstants.instance.appHeight), - Row( - children: [ - const Spacer(), - Text( - Translator.translate('more_about_us'), - style: const TextStyle( - color: Color(0xff222D4E), - fontSize: 16, - fontWeight: FontWeight.bold, + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: context.height * 33 / AppConstants.instance.appHeight), + Stack( + children: [ + Align( + alignment: AlignmentDirectional.center, + child: Padding( + padding: const EdgeInsets.only(top: 8), + child: Text( + Translator.translate('more_about_us'), + style: const TextStyle( + color: Color(0xff222D4E), + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + ), ), - ), - const Spacer(), - GestureDetector( - onTap: () { - Navigator.pop(context); - }, - child: SvgPicture.asset( - 'ic_back'.svgPath, + Align( + alignment: AlignmentDirectional.centerEnd, + child: GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: SvgPicture.asset( + 'ic_back'.svgPath, + ), + ), ), + ], + ), + SizedBox(height: context.height * 54 / AppConstants.instance.appHeight), + Text( + Translator.translate('main_target'), + style: const TextStyle(color: Color(0xff178756), fontSize: 16), + ), + SizedBox(height: context.height * 11 / AppConstants.instance.appHeight), + SingleChildScrollView( + child: FutureBuilder( + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.done) { + return Text( + snapshot.data as String, + textDirection: TextDirection.rtl, + style: const TextStyle( + color: Color(0xff636E88), + fontSize: 13, + ), + textAlign: TextAlign.justify, + ); + } + return const CircularProgressIndicator(); + }, + future: rootBundle.loadString('assets/meta/about_us.txt'), ), - ], - ), - SizedBox(height: context.height * 54 / AppConstants.instance.appHeight), - Text( - Translator.translate('main_target'), - style: const TextStyle(color: Color(0xff178756), fontSize: 16), - ), - SizedBox(height: context.height * 11 / AppConstants.instance.appHeight), - SingleChildScrollView( - child: FutureBuilder( - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.done) { - return Text( - snapshot.data as String, - textDirection: TextDirection.rtl, - style: const TextStyle( - color: Color(0xff636E88), - fontSize: 13, - ), - textAlign: TextAlign.justify, - ); - } - return const CircularProgressIndicator(); - }, - future: rootBundle.loadString('assets/meta/about_us.txt'), ), - ), - SizedBox(height: context.height * 20 / AppConstants.instance.appHeight), - Text( - Translator.translate('contact_to_us'), - style: const TextStyle(color: Color(0xff178756), fontSize: 16), - ), - SizedBox(height: context.height * 24 / AppConstants.instance.appHeight), - Row( - children: [ - GestureDetector( - onTap: _openInstagram, - child: Row( - children: [ - const Text( - 'Sonnat_islam', - style: TextStyle(color: Color(0xff404966), fontSize: 13), - ), - SizedBox(width: context.width * 15 / AppConstants.instance.appWidth), - SvgPicture.asset('ic_instagram'.svgPath), - ], + SizedBox(height: context.height * 20 / AppConstants.instance.appHeight), + Text( + Translator.translate('contact_to_us'), + style: const TextStyle(color: Color(0xff178756), fontSize: 16), + ), + SizedBox(height: context.height * 24 / AppConstants.instance.appHeight), + Row( + children: [ + GestureDetector( + onTap: _openInstagram, + child: Row( + children: [ + const Text( + 'Sonnat_islam', + style: TextStyle(color: Color(0xff404966), fontSize: 13), + ), + SizedBox(width: context.width * 15 / AppConstants.instance.appWidth), + SvgPicture.asset('ic_instagram'.svgPath), + ], + ), ), - ), - const Spacer(), - GestureDetector( - onTap: _openPhone, - child: Row( - children: [ - const Text( - '+98 92300264', - textDirection: TextDirection.ltr, - style: TextStyle(color: Color(0xff404966), fontSize: 13), - ), - SizedBox(width: context.width * 15 / AppConstants.instance.appWidth), - SvgPicture.asset('ic_phone'.svgPath), - ], + const Spacer(), + GestureDetector( + onTap: _openPhone, + child: Row( + children: [ + const Text( + '+98 92300264', + textDirection: TextDirection.ltr, + style: TextStyle(color: Color(0xff404966), fontSize: 13), + ), + SizedBox(width: context.width * 15 / AppConstants.instance.appWidth), + SvgPicture.asset('ic_phone'.svgPath), + ], + ), ), - ), - ], - ), - SizedBox(height: context.height * 29 / AppConstants.instance.appHeight), - Text( - Translator.translate('send_message_to_us'), - style: const TextStyle(color: Color(0xff404966), fontSize: 12), - ), - SizedBox(height: context.height * 12 / AppConstants.instance.appHeight), - TextFormField( - autofocus: true, - maxLength: 300, - controller: _controller, - maxLines: 10, - minLines: 4, - style: const TextStyle( - color: Color(0xff8D95AB), - fontSize: 10, + ], ), - decoration: InputDecoration( - fillColor: Colors.transparent, - hintText: Translator.translate('send_message'), - filled: true, - counterText: '', - hintStyle: const TextStyle( + SizedBox(height: context.height * 29 / AppConstants.instance.appHeight), + Text( + Translator.translate('send_message_to_us'), + style: const TextStyle(color: Color(0xff404966), fontSize: 12), + ), + SizedBox(height: context.height * 12 / AppConstants.instance.appHeight), + TextFormField( + autofocus: false, + maxLength: 300, + controller: _controller, + maxLines: 10, + minLines: 4, + style: const TextStyle( color: Color(0xff8D95AB), fontSize: 10, ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide(color: Color(0xff636E88)), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide( - color: Color(0xff636E88), + decoration: InputDecoration( + fillColor: Colors.transparent, + hintText: Translator.translate('send_message'), + filled: true, + counterText: '', + hintStyle: const TextStyle( + color: Color(0xff8D95AB), + fontSize: 10, + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide(color: Color(0xff636E88)), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide( + color: Color(0xff636E88), + ), ), ), ), - ), - SizedBox(height: context.height * 9 / AppConstants.instance.appHeight), - Container( - decoration: BoxDecoration( - color: const Color(0xff178756), - borderRadius: BorderRadius.circular(12), - ), - padding: EdgeInsets.symmetric( - horizontal: context.width * 20 / AppConstants.instance.appWidth, - vertical: context.height * 10 / AppConstants.instance.appHeight, - ), - child: Text( - Translator.translate('send'), - style: const TextStyle(color: Color(0xffffffff), fontSize: 12), + SizedBox(height: context.height * 9 / AppConstants.instance.appHeight), + Container( + decoration: BoxDecoration( + color: const Color(0xff178756), + borderRadius: BorderRadius.circular(12), + ), + padding: EdgeInsets.symmetric( + horizontal: context.width * 20 / AppConstants.instance.appWidth, + vertical: context.height * 10 / AppConstants.instance.appHeight, + ), + child: Text( + Translator.translate('send'), + style: const TextStyle(color: Color(0xffffffff), fontSize: 12), + ), ), - ), - ], + ], + ), ), ), ); diff --git a/lib/features/main/widget/main_item_widget.dart b/lib/features/main/widget/main_item_widget.dart index 7c0d1ae..b5a63ea 100644 --- a/lib/features/main/widget/main_item_widget.dart +++ b/lib/features/main/widget/main_item_widget.dart @@ -22,14 +22,19 @@ class MainItemWidget extends StatelessWidget { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - SvgPicture.asset(icon.svgPath), + SvgPicture.asset( + icon.svgPath, + height: 35, + width: 35, + ), SizedBox(height: context.height * 8 / AppConstants.instance.appHeight), Text( name, style: const TextStyle( color: Colors.white, - fontSize: 16, + fontSize: 14, ), + textAlign: TextAlign.center, ), ], ), diff --git a/lib/features/posts/screen/posts_screen.dart b/lib/features/posts/screen/posts_screen.dart index 8da8876..c3b6e73 100644 --- a/lib/features/posts/screen/posts_screen.dart +++ b/lib/features/posts/screen/posts_screen.dart @@ -4,9 +4,12 @@ import 'package:flutter_svg/flutter_svg.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/widgets/loading_list_widget.dart'; +import 'package:sonnat/features/aabout_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'; @@ -118,40 +121,50 @@ class _PostsScreenState extends State { ), ], ) - : Row( + : Stack( children: [ - GestureDetector( - onTap: () {}, - child: SvgPicture.asset( - 'ic_more'.svgPath, + Align( + alignment: AlignmentDirectional.centerStart, + child: GestureDetector( + onTap: _showOptions, + child: SvgPicture.asset( + 'ic_more'.svgPath, + ), ), ), - SizedBox(width: context.width * 8 / AppConstants.instance.appWidth), - GestureDetector( - onTap: () { - setState(() { - _searchMode = !_searchMode; - }); - }, - child: SvgPicture.asset( - 'ic_rounded_search'.svgPath, + PositionedDirectional( + start: context.width * 44 / AppConstants.instance.appWidth, + child: GestureDetector( + onTap: () { + setState(() { + _searchMode = !_searchMode; + }); + }, + child: SvgPicture.asset('ic_rounded_search'.svgPath), ), ), - const Spacer(), - Text( - widget.title, - style: const TextStyle( - color: Color(0xff404966), - fontSize: 22, + Align( + alignment: AlignmentDirectional.center, + child: Padding( + padding: const EdgeInsets.only(top: 8), + child: Text( + widget.title, + style: const TextStyle( + color: Color(0xff404966), + fontSize: 22, + ), + ), ), ), - const Spacer(), - GestureDetector( - onTap: () { - Navigator.pop(context); - }, - child: SvgPicture.asset( - 'ic_back'.svgPath, + Align( + alignment: AlignmentDirectional.centerEnd, + child: GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: SvgPicture.asset( + 'ic_back'.svgPath, + ), ), ), ], @@ -200,8 +213,8 @@ class _PostsScreenState extends State { : _cubit.query.isEmpty ? '' : _cubit.searchedList.isEmpty - ? "موردی یافت نشد" - : "${_cubit.searchedList.length} مورد یافت شد", + ? 'موردی یافت نشد' + : '${_cubit.searchedList.length} مورد یافت شد', style: const TextStyle( color: Color(0xff636E88), fontSize: 12, @@ -273,6 +286,74 @@ class _PostsScreenState extends State { ), ); } + + 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 { @@ -281,3 +362,25 @@ class FilterItem { const FilterItem({required this.selected, required this.title}); } + +class MoreOptionsWidget extends StatelessWidget { + final String title; + final Function() onTap; + + const MoreOptionsWidget({super.key, required this.title, required this.onTap}); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: onTap, + child: Text( + title, + style: const TextStyle( + color: Color(0xff222D4E), + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + ); + } +} diff --git a/lib/features/single_post/screen/single_post_screen.dart b/lib/features/single_post/screen/single_post_screen.dart index ba12f0d..5e1cff7 100644 --- a/lib/features/single_post/screen/single_post_screen.dart +++ b/lib/features/single_post/screen/single_post_screen.dart @@ -1,4 +1,3 @@ -import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -9,7 +8,6 @@ import 'package:sonnat/core/language/translator.dart'; import 'package:sonnat/core/utils/app_constants.dart'; import 'package:sonnat/core/utils/app_utils.dart'; import 'package:sonnat/core/utils/base_cubit_type.dart'; -import 'package:sonnat/core/widgets/shimmer.dart'; import 'package:sonnat/features/single_post/cubit/single_post_cubit.dart'; import 'package:sonnat/features/single_post/view_models/post.dart'; import 'package:sonnat/features/single_post/widget/add_comment_widget.dart'; @@ -57,14 +55,17 @@ class _SinglePostScreenState extends State { widget.post.image, fit: BoxFit.cover, ), - const Positioned( - top: 0, - left: 8, - right: 8, - child: Row( - children: [ - BackButton(color: Colors.white), - ], + PositionedDirectional( + end: 16, + top: 16, + child: GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: const Icon( + Icons.arrow_forward_rounded, + color: Colors.white, + ), ), ), Positioned( @@ -155,6 +156,7 @@ class _SinglePostScreenState extends State { padding: EdgeInsetsDirectional.only( start: context.width * 26 / AppConstants.instance.appWidth, end: context.width * 37 / AppConstants.instance.appWidth, + top: 16, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, diff --git a/lib/features/splash/cubit/splash_cubit.dart b/lib/features/splash/cubit/splash_cubit.dart new file mode 100644 index 0000000..9ab2599 --- /dev/null +++ b/lib/features/splash/cubit/splash_cubit.dart @@ -0,0 +1,28 @@ +import 'package:data/app_setting_data/repository/app_setting_box_repository_impl.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:local_db_core/lib/boxes/box_list/setting_box/app_setting_box.dart'; +import 'package:repositories/app_setting_box_domain/repository/app_setting_box_repository.dart'; +import 'package:sonnat/core/utils/base_cubit_type.dart'; + +class SplashCubit extends Cubit> { + final AppSettingBoxRepository _repository = AppSettingBoxRepositoryImpl(appSettingBox: AppSettingBox()); + + SplashCubit() : super(BaseCubitType(eventName: SplashCubitState.empty)); + + void empty() => emit(BaseCubitType(eventName: SplashCubitState.empty)); + + Future checkLanguageSet() async { + String? language = _repository.getCurrentLanguage(); + if(language == null || language == '') { + emit(BaseCubitType(eventName: SplashCubitState.notSet)); + } else { + emit(BaseCubitType(eventName: SplashCubitState.set)); + } + } +} + +enum SplashCubitState { + empty, + set, + notSet, +} diff --git a/lib/features/splash/screen/splash_screen.dart b/lib/features/splash/screen/splash_screen.dart new file mode 100644 index 0000000..33d3d6a --- /dev/null +++ b/lib/features/splash/screen/splash_screen.dart @@ -0,0 +1,83 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:sonnat/core/extensions/context_extension.dart'; +import 'package:sonnat/core/extensions/string_extension.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/features/main/main_screen.dart'; +import 'package:sonnat/features/splash/cubit/splash_cubit.dart'; + +class SplashScreen extends StatefulWidget { + const SplashScreen({super.key}); + + @override + State createState() => _SplashScreenState(); +} + +class _SplashScreenState extends State { + late final SplashCubit _cubit; + + @override + void initState() { + _cubit = BlocProvider.of(context); + Future.delayed(const Duration(milliseconds: 2500), _cubit.checkLanguageSet); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: const Color(0xff26237A), + body: BlocBuilder>( + builder: (context, state) { + switch (state.eventName!) { + case SplashCubitState.empty: + break; + case SplashCubitState.set: + WidgetsBinding.instance.addPostFrameCallback((timeStamp) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) { + return const MainScreen(); + }, + ), + ); + }); + break; + case SplashCubitState.notSet: + WidgetsBinding.instance.addPostFrameCallback((timeStamp) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) { + return BlocProvider( + create: (context) => SelectLanguageCubit(), + child: const SelectLanguageScreen(), + ); + }, + ), + ); + }); + break; + } + return Center( + child: Container( + margin: EdgeInsets.only( + left: context.width * 86 / AppConstants.instance.appWidth, + right: context.width * 86 / AppConstants.instance.appWidth, + ), + child: Image.asset( + 'ic_main_header'.pngPath, + width: context.width * 200 / AppConstants.instance.appWidth, + height: context.height * 200 / AppConstants.instance.appHeight, + ), + ), + ); + }, + ), + ); + } +} diff --git a/lib/main.dart b/lib/main.dart index efe0e54..9a368aa 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,6 +1,3 @@ -import 'dart:async'; - -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -10,18 +7,13 @@ import 'package:sonnat/core/theme/cubit/theme_cubit.dart'; import 'package:sonnat/core/utils/app_utils.dart'; import 'package:sonnat/core/utils/base_cubit_type.dart'; import 'package:sonnat/core/utils/initializer.dart'; -import 'package:sonnat/features/main/main_screen.dart'; +import 'package:sonnat/features/splash/cubit/splash_cubit.dart'; +import 'package:sonnat/features/splash/screen/splash_screen.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); await Initializer.instance.initialHive(); - if (!kDebugMode) { - await runZonedGuarded>(() async { - runApp(const MyApp()); - }, (error, stackTrace) async {}); - } else { - runApp(const MyApp()); - } + runApp(const MyApp()); } class MyApp extends StatelessWidget { @@ -30,6 +22,7 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]); + SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []); return MultiBlocProvider( providers: [ BlocProvider(create: (context) => LanguageCubit()), @@ -52,67 +45,59 @@ class _MyHomePageState extends State { Widget build(BuildContext context) { return BlocBuilder>( builder: (context, state) { - if (state.eventName == LanguageState.loaded) { - Initializer.instance.setAppDirection( - state.data == CurrentLanguage.fa || state.data == CurrentLanguage.ar ? 'rtl' : 'ltr', - ); - return MaterialApp( - builder: (context, child) { - Widget error = const Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'خطا در نمابش اطلاعات', - style: TextStyle( - color: Colors.black, - fontWeight: FontWeight.w700, - fontSize: 18, - ), - textAlign: TextAlign.center, - ), - ], - ), - ); - if (child is Scaffold || child is Navigator) { - error = Scaffold( - body: SafeArea( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - error, - const Icon( - Icons.error_outline_rounded, - size: 130, - color: Colors.red, - ), - ], + return MaterialApp( + builder: (context, child) { + Widget error = const Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'خطا در نمابش اطلاعات', + style: TextStyle( + color: Colors.black, + fontWeight: FontWeight.w700, + fontSize: 18, ), + textAlign: TextAlign.center, + ), + ], + ), + ); + if (child is Scaffold || child is Navigator) { + error = Scaffold( + body: SafeArea( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + error, + const Icon( + Icons.error_outline_rounded, + size: 130, + color: Colors.red, + ), + ], ), - ); - } - ErrorWidget.builder = (errorDetails) => error; - return ScrollConfiguration( - behavior: DisableScrollEffect().copyWith(scrollbars: false), - child: Directionality( - textDirection: Initializer.instance.getTextDirection(), - child: child!, ), ); - }, - theme: Utils.instance.getAppTheme(context, state.data), - debugShowCheckedModeBanner: false, - supportedLocales: Translator.supportedLocales(), - initialRoute: '/', - routes: { - '/': (context) => const MainScreen(), - }, - ); - } - return MaterialApp( + } + ErrorWidget.builder = (errorDetails) => error; + return ScrollConfiguration( + behavior: DisableScrollEffect().copyWith(scrollbars: false), + child: Directionality( + textDirection: Initializer.instance.getTextDirection(), + child: child!, + ), + ); + }, + theme: Utils.instance.getAppTheme(context), debugShowCheckedModeBanner: false, - builder: (context, child) { - return Container(color: Colors.white); + supportedLocales: Translator.supportedLocales(), + initialRoute: '/', + routes: { + '/': (context) => BlocProvider( + create: (context) => SplashCubit(), + child: const SplashScreen(), + ), }, ); }, diff --git a/pubspec.lock b/pubspec.lock index 60efb51..0b55be2 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -109,10 +109,10 @@ packages: dependency: transitive description: name: cli_util - sha256: "66f86e916d285c1a93d3b79587d94bd71984a66aac4ff74e524cfa7877f1395c" + sha256: b8db3080e59b2503ca9e7922c3df2072cf13992354d5e944074ffa836fba43b7 url: "https://pub.dev" source: hosted - version: "0.3.5" + version: "0.4.0" clock: dependency: transitive description: @@ -225,10 +225,10 @@ packages: dependency: "direct dev" description: name: flutter_launcher_icons - sha256: a9de6706cd844668beac27c0aed5910fa0534832b3c2cad61a5fd977fce82a5d + sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea" url: "https://pub.dev" source: hosted - version: "0.10.0" + version: "0.13.1" flutter_lints: dependency: "direct dev" description: @@ -307,10 +307,10 @@ packages: dependency: transitive description: name: image - sha256: "8e9d133755c3e84c73288363e6343157c383a0c6c56fc51afcc5d4d7180306d6" + sha256: a72242c9a0ffb65d03de1b7113bc4e189686fc07c7147b8b41811d0dd0e0d9bf url: "https://pub.dev" source: hosted - version: "3.3.0" + version: "4.0.17" intl: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 3a547c1..c6d2f05 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -37,7 +37,7 @@ dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^2.0.0 - flutter_launcher_icons: ^0.10.0 + flutter_launcher_icons: ^0.13.1 flutter: uses-material-design: true assets: @@ -67,4 +67,9 @@ flutter: - asset: assets/fonts/arabi/Cairo-Light.ttf - asset: assets/fonts/arabi/Cairo-Medium.ttf - asset: assets/fonts/arabi/Cairo-Regular.ttf - - asset: assets/fonts/arabi/Cairo-SemiBold.ttf \ No newline at end of file + - asset: assets/fonts/arabi/Cairo-SemiBold.ttf + +flutter_icons: + android: "launcher_icon" + ios: true + image_path: "assets/images/png/logo.png" \ No newline at end of file