import 'package:flutter/cupertino.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:tangheem/api/tangheem_user_api_client.dart'; import 'package:tangheem/app_state/app_state.dart'; import 'package:tangheem/classes/colors.dart'; import 'package:tangheem/classes/consts.dart'; import 'package:tangheem/classes/utils.dart'; import 'package:tangheem/models/aya_model.dart'; import 'package:tangheem/models/aya_tangheem_type_mapped.dart'; import 'package:tangheem/models/bookmark_model.dart'; import 'package:tangheem/models/surah_model.dart'; import 'package:tangheem/widgets/common_dropdown_button.dart'; import 'tangheem_detail_screen.dart'; class QuranScreen extends StatefulWidget { static const String routeName = "/quran"; final BookMarkModel bookmark; QuranScreen({Key key, this.bookmark}) : super(key: key); @override _QuranScreenState createState() { return _QuranScreenState(bookmark); } } class _QuranScreenState extends State { int _selectedSurah = -1; int _selectedFromAya = -1; int _selectedToAya = -1; int _currentSurahIndex = -1; int _currentPage = 0; List _surahList = []; List _fromAyaList = []; List _toAyaList = []; SurahModel _surahModel; AyatTangheemTypeMapped _ayatTangheemTypeMapped; AyaModel _ayaModel; List _tangheemWords = []; _QuranScreenState(this._selectedAyaForBookmark); @override void initState() { super.initState(); getBookMark(); getPrefs(); getSurah(); } int fontSize = 18; SharedPreferences prefs; void getPrefs() async { prefs = await SharedPreferences.getInstance(); fontSize = (prefs.getInt(GlobalConsts.fontZoomSize) ?? 18); setState(() {}); } void getSurah() async { try { if (AppState().getSurahModel == null) { Utils.showLoading(context); _surahModel = await TangheemUserApiClient().getSurahs(); AppState().setSurahModel(_surahModel); } else { _surahModel = AppState().getSurahModel; } _surahList = _surahModel.data.map((element) => element.nameAR).toList(); _currentPage = widget.bookmark?.page ?? 1; Utils.hideLoading(context); } catch (ex) { Utils.hideLoading(context); if (mounted) Utils.handleException(ex, null); } setState(() {}); getQuranByPageNo(); // getTangheemBySurahId(); } List _bookMark = []; void getBookMark() async { _bookMark = await BookMarkModel.getFromPrefs(); if (_bookMark.length == 1) { _selectedAyaForBookmark = _selectedAyaForBookmark ?? _bookMark.first; } else if (_bookMark.length > 1) { _selectedAyaForBookmark = _selectedAyaForBookmark ?? _bookMark.last; } setState(() {}); } int numberOfAyah = 0; var filteredAyahList = []; void filterData() { numberOfAyah = _surahModel?.data[_selectedSurah]?.numberOfAyahs ?? 0; filteredAyahList = List.generate(numberOfAyah, (index) => index + 1).toList().where((element) => element == 1 || (element % 5) == 0 || element == numberOfAyah).toList() ?? []; _fromAyaList = filteredAyahList.getRange(0, filteredAyahList.length - 1)?.toList() ?? []; setState(() {}); } Future> getTangheemBySurahId(int surahId, int numberInSurah) async { Utils.showLoading(context); try { AyatTangheemTypeMapped _ayatTangheemTypeMapped = await TangheemUserApiClient().getTangheemBySurah(surahId, numberInSurah); Utils.hideLoading(context); return _ayatTangheemTypeMapped.data; } catch (ex) { Utils.hideLoading(context); // if (mounted) Utils.handleException(ex, null); return []; } } void getAyaByRange() async { Utils.showLoading(context); try { _ayaModel = await TangheemUserApiClient().getAyaByFilter(_selectedSurah + 1, _fromAyaList[_selectedFromAya], _toAyaList[_selectedToAya]); } catch (ex) { if (mounted) Utils.handleException(ex, null); } finally { Utils.hideLoading(context); } setState(() {}); } void getQuranByPageNo() async { Utils.showLoading(context); try { _ayaModel = await TangheemUserApiClient().getQuranByPageNo(_currentPage); // await getTangheemBySurahId(); Utils.hideLoading(context); setState(() {}); } catch (ex) { if (mounted) Utils.handleException(ex, null); Utils.hideLoading(context); } } int getNextMultiple(int num) { int multipleOf = 5; int nextDiff = multipleOf - (num % multipleOf); int total = num + nextDiff; return total; } @override void dispose() { super.dispose(); } String getBismillahWithSurahName(int _surahID, String _surahName, bool isShowBismillah, bool isFirstIsAya) { String _bismillah = "\n بِسۡمِ ٱللَّهِ ٱلرَّحۡمَٰنِ ٱلرَّحِيم"; if (_surahID == 9) { _bismillah = ""; } if (isFirstIsAya && isShowBismillah) { return "" + _surahName + "$_bismillah \n"; } else if (isShowBismillah) { return "\n" + _surahName + "$_bismillah \n"; } return "" + _surahName + "\n"; } void _clearFilterAndRefreshData() { _selectedSurah = -1; _selectedFromAya = -1; _selectedToAya = -1; getQuranByPageNo(); } @override Widget build(BuildContext context) { var tempList = _ayaModel?.data?.map((e) => e.surahNameAR)?.toList()?.toSet()?.toList() ?? []; String _surahName = ""; _surahName = tempList.isEmpty ? "" : tempList?.last ?? ""; int index = _surahList.indexWhere((element) => element == _surahName); if (index != null) { _currentSurahIndex = index; } String _surahAya = ""; _ayaModel?.data?.forEach((element) { var temp = element.numberInSurah == 1 ? getBismillahWithSurahName(element.surahID, element.surahNameAR, element.surahID != 1, _surahAya.length <= 1) + element.reverseAyatNumber() : element.reverseAyatNumber(); _surahAya = _surahAya + temp + " "; }); _surahAya = _surahAya + "\n" + "$_currentPage"; List widList = [ Text( "اقرأ القرآن الكريم", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20, color: ColorConsts.primaryBlue, height: 1), ), SizedBox(height: 4), Text( "قراءة وسماع آيات القرآن الكريم", style: TextStyle(fontWeight: FontWeight.w600, fontSize: 16, color: ColorConsts.primaryBlue), ), SizedBox(height: 4), Text( "اضغط الآية المرغوبة لمزيد من التفاصيل", style: TextStyle( fontSize: 12, color: ColorConsts.primaryBlue, ), ), SizedBox(height: 16), Row( children: [ Expanded( child: CommonDropDownButton(_selectedSurah, hintText: "اختر السورة", list: _surahList, onSelect: (index) { if (_selectedSurah != index) { _selectedSurah = index; _selectedToAya = -1; _selectedFromAya = -1; _toAyaList = []; filterData(); } }), ), SizedBox(width: 4), Expanded( child: CommonDropDownButton(_selectedFromAya, hintText: "من الآية", list: _fromAyaList.map((e) => "من الآية" + " $e").toList(), onSelect: (index) { if (_selectedFromAya != index) { _selectedFromAya = index; _selectedToAya = -1; filteredAyahList.indexOf(_selectedFromAya); _toAyaList = filteredAyahList.getRange(_selectedFromAya + 1, filteredAyahList.length)?.toList() ?? []; setState(() {}); } }), ), SizedBox(width: 4), Expanded( child: CommonDropDownButton(_selectedToAya, hintText: "إلى الآية", list: _toAyaList.map((e) => "إلى الآية" + " $e").toList(), onSelect: (index) { if (_selectedToAya != index) { _selectedToAya = index; setState(() {}); } }), ), ], ), SizedBox(height: 8), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ commonIconButton("عرض", "assets/icons/go_forward.svg", () { if (_selectedSurah < 0) { Utils.showToast("يرجى اختيار السورة"); return; } else { if (_selectedFromAya < 0 && _selectedToAya < 0) { _currentPage = _surahModel?.data[_selectedSurah]?.startPageNo; getQuranByPageNo(); return; } if (_selectedFromAya >= 0 && _selectedToAya >= 0) { getAyaByRange(); return; } } }), Row( mainAxisSize: MainAxisSize.min, children: [ zoomButtons("assets/icons/reduce_size.svg", () { if (fontSize <= 12) { Utils.showToast("وصل حجم الخط إلى الحد الأدنى للحجم"); return; } fontSize -= 2; prefs.setInt(GlobalConsts.fontZoomSize, fontSize); setState(() {}); }), zoomButtons("assets/icons/increase_size.svg", () { if (fontSize >= 36) { Utils.showToast("وصل حجم الخط إلى الحد الأقصى للحجم"); return; } fontSize += 2; prefs.setInt(GlobalConsts.fontZoomSize, fontSize); setState(() {}); }), ], ) ], ), SizedBox(height: 16), ]; Widget quranTextView = SingleChildScrollView( physics: BouncingScrollPhysics(), child: Padding( padding: EdgeInsets.only(left: 4, right: 4), child: quranText(), ), ); if (MediaQuery.of(context).orientation == Orientation.portrait) { quranTextView = Expanded(child: quranTextView); } Widget quranView = Container( margin: EdgeInsets.only(top: 4, bottom: 4), padding: EdgeInsets.only(top: 16, bottom: 4, right: 16, left: 16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), ), child: Column( mainAxisSize: MainAxisSize.min, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ nextOptionButton( "assets/icons/prev.svg", _currentSurahIndex <= 0 ? "" : Utils.getNotNullValue(_surahList, _currentSurahIndex - 1) ?? "", _currentSurahIndex <= 0 ? null : (value) { _currentPage = _surahModel?.data?.elementAt(_surahList.indexOf(value))?.startPageNo ?? _currentPage; _clearFilterAndRefreshData(); }), previousOptionButton( "assets/icons/next.svg", _currentSurahIndex >= (_surahList.isNotEmpty ? (_surahList.length - 1) : 0) ? "" : Utils.getNotNullValue(_surahList, _currentSurahIndex + 1) ?? "", _currentSurahIndex >= (_surahList.isNotEmpty ? (_surahList.length - 1) : 0) ? null : (value) { _currentPage = _surahModel?.data?.singleWhere((element) => element.nameAR == value)?.startPageNo ?? _currentPage; _clearFilterAndRefreshData(); }), ], ), quranTextView, SizedBox(height: 4), if (_selectedFromAya == -1 && _selectedToAya == -1) Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ nextOptionButton( "assets/icons/prev_single.svg", "الصفحة السابقة", _currentPage <= 1 ? null : (value) { _currentPage = _currentPage - 1; _clearFilterAndRefreshData(); }), previousOptionButton( "assets/icons/next_single.svg", "الصفحة التالية", _currentPage == 604 ? null : (value) { _currentPage = _currentPage + 1; _clearFilterAndRefreshData(); }), ], ), ], ), ); if (MediaQuery.of(context).orientation == Orientation.portrait) { quranView = Expanded(child: quranView); } List finalViewList = [] + widList + [if (_surahAya.isNotEmpty) quranView]; var multiModeView; if (MediaQuery.of(context).orientation == Orientation.portrait) { multiModeView = Padding( padding: EdgeInsets.fromLTRB(16, 24, 16, 0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: finalViewList, ), ); } else { multiModeView = ListView( padding: EdgeInsets.fromLTRB(16, 24, 16, 0), physics: BouncingScrollPhysics(), children: finalViewList, ); } return SizedBox(width: double.infinity, child: multiModeView); } Widget commonIconButton(String title, String iconString, VoidCallback callback) { return InkWell( splashColor: Colors.transparent, highlightColor: Colors.transparent, onTap: callback, child: Container( height: 36, decoration: BoxDecoration( color: callback == null ? ColorConsts.secondaryPink.withOpacity(.5) : ColorConsts.secondaryPink, borderRadius: BorderRadius.circular(6), ), padding: EdgeInsets.fromLTRB(8, 2, 8, 2), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ Text( title, maxLines: 1, style: TextStyle(fontSize: 12, color: Colors.white), ), SizedBox(width: 12), SvgPicture.asset(iconString, width: 20, height: 20, color: Colors.white), ], ), ), ); } Widget nextOptionButton(String icon, String text, Function(String) onPressed) { return InkWell( onTap: () => onPressed(text), child: onPressed == null ? SizedBox() : Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ SvgPicture.asset(icon, height: 12, width: 12), SizedBox(width: 4), Text( text, style: TextStyle(color: ColorConsts.textGrey), ), ], ), ); } void _selectTangheemType(List list, List dataList) async { SimpleDialog dialog = SimpleDialog( title: Text( 'اختر نوع تنغيم', textDirection: TextDirection.rtl, style: TextStyle(color: ColorConsts.primaryBlack), ), children: list .map((e) => SimpleDialogOption( child: Text( e, textDirection: TextDirection.rtl, style: TextStyle(color: ColorConsts.primaryBlue), ), onPressed: () { Navigator.pop(context); var list = dataList.where((element) => element.tangheemTypeName == e)?.toList() ?? []; var name = dataList.firstWhere((element) => element.tangheemTypeName == e, orElse: null); TangheemDetailParams tangheem = TangheemDetailParams(selectedTangheemTypeId: name?.ayaTangheemTypeId ?? "", ayatTangheemTypeMappedDataList: list); Navigator.pushNamed(context, TangheemDetailScreen.routeName, arguments: tangheem); }, )) .toList(), ); await showDialog( context: context, builder: (BuildContext context) { return dialog; }, ); } Widget previousOptionButton(String icon, String text, Function(String) onPressed) { return InkWell( onTap: () => onPressed(text), child: onPressed == null ? SizedBox() : Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ Text( text, style: TextStyle(color: ColorConsts.textGrey), ), SizedBox(width: 4), SvgPicture.asset(icon, height: 12, width: 12), ], ), ); } BookMarkModel _selectedAyaForBookmark; Widget quranText() { List textSpanList = []; String _surahAya = ""; _ayaModel?.data?.forEach((element) { var temp = element.numberInSurah == 1 ? getBismillahWithSurahName(element.surahID, element.surahNameAR, element.surahID != 1, _surahAya.length <= 1) + element.reverseAyatNumber() : element.ayahText; textSpanList.add(TextSpan( text: temp + " ", style: TextStyle( backgroundColor: _selectedAyaForBookmark?.ayahID == element.ayahID ? ColorConsts.secondaryOrange.withOpacity(.4) : Colors.transparent, fontFamily: "UthmanicHafs", fontSize: fontSize.toDouble(), color: ColorConsts.primaryBlue, fontWeight: FontWeight.bold, ), recognizer: TapGestureRecognizer() ..onTap = () { setState(() { if (_selectedAyaForBookmark == null) { _selectedAyaForBookmark = BookMarkModel.fromJson(element.toJson()); showAyaOptions(element); return; } _selectedAyaForBookmark = null; }); }, )); _surahAya = _surahAya + temp + " "; }); textSpanList.add( TextSpan( text: "\n" + "$_currentPage", style: TextStyle( fontFamily: "BArabics", fontSize: fontSize.toDouble(), color: ColorConsts.primaryBlue, fontWeight: FontWeight.bold, ), ), ); _surahAya = _surahAya + "\n" + "$_currentPage"; return RichText( textAlign: TextAlign.center, textWidthBasis: TextWidthBasis.parent, text: TextSpan( children: textSpanList, ), ); } void showAyaOptions(AyaModelData ayaModelData) { showModalBottomSheet( context: context, backgroundColor: Colors.transparent, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), builder: (context) { return Directionality( textDirection: TextDirection.rtl, child: Container( margin: EdgeInsets.all(16), padding: EdgeInsets.symmetric(vertical: 12, horizontal: 12), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), ), child: Column( mainAxisSize: MainAxisSize.min, children: [ InkWell( onTap: () async { Navigator.pop(context); List list = []; list = await getTangheemBySurahId(ayaModelData.surahID, ayaModelData.numberInSurah); if (list.isEmpty) { Utils.showToast("لا توجد أساليب تنغيم في هذه الآية"); return; } List tempList = list.map((element) => element.tangheemTypeName).toList().toSet().toList(); if (tempList.length > 1) { _selectTangheemType(tempList, list); return; } var name = list.firstWhere((element) => element.tangheemTypeName == tempList.first, orElse: null); TangheemDetailParams tangheem = TangheemDetailParams(selectedTangheemTypeId: name?.ayaTangheemTypeId ?? "", ayatTangheemTypeMappedDataList: list); Navigator.pushNamed(this.context, TangheemDetailScreen.routeName, arguments: tangheem); }, child: Row( children: [Text("تفاصيل الأساليب")], ), ), SizedBox(height: 8), InkWell( onTap: () { Navigator.pop(context); var temp = _bookMark.firstWhere((element) => element.ayahID == _selectedAyaForBookmark.ayahID, orElse: () => null); if (temp != null) { Utils.showToast("هذه الآية مضافة سابقا"); return; } _bookMark.add(_selectedAyaForBookmark); BookMarkModel.saveToPrefs(_bookMark); Utils.showToast("تم إضافة الآية كمرجع"); }, child: Row( children: [Text("إضافة الآية كمرجع")], ), ), ], ), ), ); }); } Widget zoomButtons(String icon, VoidCallback onPressed, {double size, bool isAsset = true}) { return IconButton( padding: EdgeInsets.zero, icon: SvgPicture.asset(icon, height: size ?? 24, width: size ?? 24), onPressed: onPressed, ); } } class TangheemTemp { final String tangheemName; final String ayaTangheemId; TangheemTemp(this.tangheemName, this.ayaTangheemId); }