From f369aa6108b194e3f5bfda3aeb88274ed6df211f Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Wed, 31 Mar 2021 12:03:20 +0300 Subject: [PATCH] quran screen app flow improvements. --- lib/api/tangheem_user_api_client.dart | 6 ++ lib/main.dart | 6 +- lib/ui/common_appbar.dart | 4 +- lib/ui/screens/home_screen.dart | 89 ++++++++++--------- .../{surah_screen.dart => quran_screen.dart} | 78 +++++++++++++--- lib/widgets/aya_player_widget.dart | 28 +++--- lib/widgets/text_highlight_widget.dart | 23 +++-- 7 files changed, 152 insertions(+), 82 deletions(-) rename lib/ui/screens/{surah_screen.dart => quran_screen.dart} (80%) diff --git a/lib/api/tangheem_user_api_client.dart b/lib/api/tangheem_user_api_client.dart index fb119f7..06814cb 100644 --- a/lib/api/tangheem_user_api_client.dart +++ b/lib/api/tangheem_user_api_client.dart @@ -23,6 +23,12 @@ class TangheemUserApiClient { return await ApiClient().postJsonForObject((json) => SurahModel.fromJson(json), url, postParams); } + Future getTangheemBySurah(int surahId) async { + String url = "${ApiConsts.tangheemUsers}AyatTangheemTypeMapped_Get"; + var postParams = {"surahNo": surahId}; + return await ApiClient().postJsonForObject((json) => AyatTangheemTypeMapped.fromJson(json), url, postParams); + } + Future getAyaByRange(int itemsPerPage, int currentPageNo, int surahID, int ayahFrom, int ayahTo) async { String url = "${ApiConsts.tangheemUsers}AyatByRange_Get"; var postParams = {"itemsPerPage": itemsPerPage, "currentPageNo": currentPageNo, "surahID": surahID, "ayahFrom": ayahFrom, "ayahTo": ayahTo}; diff --git a/lib/main.dart b/lib/main.dart index 82dbef8..962fe91 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -7,7 +7,7 @@ import 'ui/screens/forgot_password_screen.dart'; import 'ui/screens/home_screen.dart'; import 'ui/screens/login_screen.dart'; import 'ui/screens/registration_screen.dart'; -import 'ui/screens/surah_screen.dart'; +import 'ui/screens/quran_screen.dart'; import 'ui/screens/tangheem_detail_screen.dart'; import 'classes/colors.dart'; import 'ui/screens/tangheem_screen.dart'; @@ -53,9 +53,9 @@ class Application extends StatelessWidget { child: TangheemDetailScreen(ayatTangheemTypeMappedData: settings.arguments), ); break; - case SurahScreen.routeName: + case QuranScreen.routeName: String query = settings.arguments.toString(); - className = CommonAppbar(child: SurahScreen(query: query)); + className = CommonAppbar(child: QuranScreen(query: query)); break; } return goToNavigation(className); diff --git a/lib/ui/common_appbar.dart b/lib/ui/common_appbar.dart index 46b52d5..e9ee280 100644 --- a/lib/ui/common_appbar.dart +++ b/lib/ui/common_appbar.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:tangheem/classes/colors.dart'; import 'package:tangheem/ui/screens/login_screen.dart'; -import 'package:tangheem/ui/screens/surah_screen.dart'; +import 'package:tangheem/ui/screens/quran_screen.dart'; class CommonAppbar extends StatefulWidget { final bool showDrawer; @@ -214,7 +214,7 @@ class _CommonAppbarState extends State { ), SizedBox(height: 2), myListItem("assets/icons/read_quran.svg", "اقرأ القرآن الكريم", false, onTap: () async { - await Navigator.pushNamed(context, SurahScreen.routeName, arguments: ""); + await Navigator.pushNamed(context, QuranScreen.routeName, arguments: ""); }), SizedBox(height: 2), myListItem("assets/icons/contact.svg", "الاتصال بنا", false), diff --git a/lib/ui/screens/home_screen.dart b/lib/ui/screens/home_screen.dart index 7e5e32c..9845354 100644 --- a/lib/ui/screens/home_screen.dart +++ b/lib/ui/screens/home_screen.dart @@ -8,7 +8,7 @@ import 'package:tangheem/classes/colors.dart'; import 'package:tangheem/classes/utils.dart'; import 'package:tangheem/models/surah_model.dart'; import 'package:tangheem/models/tangheem_type_model.dart'; -import 'package:tangheem/ui/screens/surah_screen.dart'; +import 'package:tangheem/ui/screens/quran_screen.dart'; import 'package:tangheem/ui/screens/tangheem_screen.dart'; import 'package:tangheem/widgets/common_dropdown_button.dart'; @@ -147,51 +147,56 @@ class _HomeScreenState extends State { ), ), SizedBox(height: 16), - Container( - height: 50, - padding: EdgeInsets.only(top: 4, bottom: 6), - child: TextField( - controller: _searchController, - focusNode: _searchFocusNode, - style: TextStyle(color: ColorConsts.primaryBlack, fontSize: 14), - decoration: InputDecoration( - contentPadding: EdgeInsets.fromLTRB(4, 4, 4, 4), - alignLabelWithHint: true, - fillColor: Colors.white, - filled: true, - hintStyle: TextStyle(color: ColorConsts.textHintGrey, fontSize: 12), - hintText: "البحث عن سورة أو آية", - prefixIconConstraints: BoxConstraints(maxHeight: 16), - prefixIcon: Padding( - padding: EdgeInsets.only(right: 6), - child: SvgPicture.asset("assets/icons/search.svg"), - ), - suffixIcon: InkWell( - onTap: () async { - _searchFocusNode.unfocus(); - _searchFocusNode.canRequestFocus = false; - await Navigator.pushNamed(context, SurahScreen.routeName, arguments: _searchController.text); - _searchFocusNode.canRequestFocus = true; - }, - splashColor: Colors.transparent, - highlightColor: Colors.transparent, - child: Container( - alignment: Alignment.center, - width: 80, - child: Text( - "بحث", - style: TextStyle(fontSize: 14, color: Colors.white), - ), - decoration: BoxDecoration( - color: ColorConsts.secondaryPink, - borderRadius: BorderRadius.only( - bottomLeft: Radius.circular(6), - topLeft: Radius.circular(6), + + // todo "Sikander" : hide this search ui, later when we have search requirement, then visible this ui. + Visibility( + visible: false, + child: Container( + height: 50, + padding: EdgeInsets.only(top: 4, bottom: 6), + child: TextField( + controller: _searchController, + focusNode: _searchFocusNode, + style: TextStyle(color: ColorConsts.primaryBlack, fontSize: 14), + decoration: InputDecoration( + contentPadding: EdgeInsets.fromLTRB(4, 4, 4, 4), + alignLabelWithHint: true, + fillColor: Colors.white, + filled: true, + hintStyle: TextStyle(color: ColorConsts.textHintGrey, fontSize: 12), + hintText: "البحث عن سورة أو آية", + prefixIconConstraints: BoxConstraints(maxHeight: 16), + prefixIcon: Padding( + padding: EdgeInsets.only(right: 6), + child: SvgPicture.asset("assets/icons/search.svg"), + ), + suffixIcon: InkWell( + onTap: () async { + _searchFocusNode.unfocus(); + _searchFocusNode.canRequestFocus = false; + await Navigator.pushNamed(context, QuranScreen.routeName, arguments: _searchController.text); + _searchFocusNode.canRequestFocus = true; + }, + splashColor: Colors.transparent, + highlightColor: Colors.transparent, + child: Container( + alignment: Alignment.center, + width: 80, + child: Text( + "بحث", + style: TextStyle(fontSize: 14, color: Colors.white), + ), + decoration: BoxDecoration( + color: ColorConsts.secondaryPink, + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(6), + topLeft: Radius.circular(6), + ), ), ), ), + border: OutlineInputBorder(borderRadius: BorderRadius.circular(6), borderSide: BorderSide.none), ), - border: OutlineInputBorder(borderRadius: BorderRadius.circular(6), borderSide: BorderSide.none), ), ), ) diff --git a/lib/ui/screens/surah_screen.dart b/lib/ui/screens/quran_screen.dart similarity index 80% rename from lib/ui/screens/surah_screen.dart rename to lib/ui/screens/quran_screen.dart index be4164d..e959fc8 100644 --- a/lib/ui/screens/surah_screen.dart +++ b/lib/ui/screens/quran_screen.dart @@ -6,26 +6,30 @@ import 'package:tangheem/api/tangheem_user_api_client.dart'; import 'package:tangheem/classes/colors.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/surah_model.dart'; import 'package:tangheem/widgets/auto_scroll_view/aya_scroll_view.dart'; import 'package:tangheem/widgets/auto_scroll_view/scroll_id.dart'; import 'package:tangheem/widgets/aya_player_widget.dart'; import 'package:tangheem/widgets/common_dropdown_button.dart'; +import 'package:tangheem/widgets/text_highlight_widget.dart'; -class SurahScreen extends StatefulWidget { +import 'tangheem_detail_screen.dart'; + +class QuranScreen extends StatefulWidget { static const String routeName = "/surah"; final SurahModel surahModel; final String query; - SurahScreen({Key key, this.surahModel, @required this.query}) : super(key: key); + QuranScreen({Key key, this.surahModel, @required this.query}) : super(key: key); @override - _SurahScreenState createState() { - return _SurahScreenState(); + _QuranScreenState createState() { + return _QuranScreenState(); } } -class _SurahScreenState extends State { +class _QuranScreenState extends State { GlobalKey _globalKey = GlobalKey(); int _selectedSurah = 0; int _selectedFromAya = 0; @@ -38,8 +42,11 @@ class _SurahScreenState extends State { List _toAyaList = []; SurahModel _surahModel; + AyatTangheemTypeMapped _ayatTangheemTypeMapped; AyaModel _ayaModel; + List _tangheemWords = []; + @override void initState() { super.initState(); @@ -73,6 +80,19 @@ class _SurahScreenState extends State { _currentPage = 0; _selectedFromAya = 0; _selectedToAya = 0; + getTangheemBySurahId(); + } + + void getTangheemBySurahId() async { + Utils.showLoading(context); + try { + _ayatTangheemTypeMapped = await TangheemUserApiClient().getTangheemBySurah(_selectedSurah + 1); + _tangheemWords = _ayatTangheemTypeMapped?.data?.map((e) => e.highlightText)?.toList() ?? []; + } catch (ex, tr) { + Utils.handleException(ex, null); + } finally { + Utils.hideLoading(context); + } getAyaByRange(); } @@ -207,12 +227,20 @@ class _SurahScreenState extends State { SizedBox(height: 8), Container( padding: EdgeInsets.only(left: 4, right: 4), - child: Text( - _surahAya, - textAlign: TextAlign.center, + child: TextHighLightWidget( + text: _surahAya, + valueColor: ColorConsts.primaryBlue, + highlights: _tangheemWords, + onTap: (value) { + List _ayatList = _ayatTangheemTypeMapped.data?.where((element) => element.highlightText == value)?.toList() ?? []; + if (_ayatList.length > 1) { + _selectTangheemType(_ayatList); + } else { + Navigator.pushNamed(context, TangheemDetailScreen.routeName, arguments: _ayatList.first); + } + }, style: TextStyle( fontFamily: "UthmanicHafs", - color: ColorConsts.primaryBlue, fontSize: 18, fontWeight: FontWeight.bold, ), @@ -271,7 +299,7 @@ class _SurahScreenState extends State { ), ), ), - AyaPlayerWidget(surahName: _surahList.isNotEmpty ? _surahList[_selectedSurah] : "", globalKey: _globalKey) + // AyaPlayerWidget(surahName: _surahList.isNotEmpty ? _surahList[_selectedSurah] : "", globalKey: _globalKey) ], ), ); @@ -297,6 +325,36 @@ class _SurahScreenState extends State { ); } + void _selectTangheemType(List list) async { + SimpleDialog dialog = SimpleDialog( + title: Text( + 'اختر نوع تنغيم', + textDirection: TextDirection.rtl, + style: TextStyle(color: ColorConsts.primaryBlack), + ), + children: list + .map((e) => SimpleDialogOption( + child: Text( + e.tangheemTypeName, + textDirection: TextDirection.rtl, + style: TextStyle(color: ColorConsts.primaryBlue), + ), + onPressed: () { + Navigator.pop(context); + Navigator.pushNamed(context, TangheemDetailScreen.routeName, arguments: e); + }, + )) + .toList(), + ); + + showDialog( + context: context, + builder: (BuildContext context) { + return dialog; + }, + ); + } + Widget previousOptionButton(String icon, String text, VoidCallback onPressed) { return InkWell( onTap: onPressed, diff --git a/lib/widgets/aya_player_widget.dart b/lib/widgets/aya_player_widget.dart index 564f7cc..7a5a7d9 100644 --- a/lib/widgets/aya_player_widget.dart +++ b/lib/widgets/aya_player_widget.dart @@ -45,26 +45,28 @@ class _AyaPlayerWidgetState extends State { setAudioSource() { try { - var voiceList = []; - if ((widget.voiceNoteList?.length ?? 0) > 0) { - voiceList = widget.voiceNoteList.map((e) => AudioSource.uri(Uri.parse(e.exposeFilePath))).toList(); - _currentVoiceNote = 0; - } - final _playlist = ConcatenatingAudioSource(children: voiceList); - _player.setAudioSource(_playlist, initialIndex: 0, initialPosition: Duration.zero).then((value) => () {}).catchError(() { - _isAudioHaveError = true; - }); + final _playlist = ConcatenatingAudioSource(children: [ + AudioSource.uri( + Uri.parse("https://file-examples-com.github.io/uploads/2017/11/file_example_MP3_1MG.mp3"), + ), + ]); + var voiceList = [AudioSource.uri(Uri.parse("https://file-examples-com.github.io/uploads/2017/11/file_example_MP3_700KB.mp3"))]; + + // if ((widget.voiceNoteList?.length ?? 0) > 0) { + // voiceList = widget.voiceNoteList.map((e) => AudioSource.uri(Uri.parse(e.exposeFilePath))).toList(); + // _currentVoiceNote = 0; + // } + // final _playlist = ConcatenatingAudioSource(children: voiceList); + _player.setAudioSource(_playlist, initialIndex: 0, initialPosition: Duration.zero).then((value) => () {}); } catch (e) { - print(e); _isAudioHaveError = true; } - print(_player.currentIndex); } @override void didUpdateWidget(covariant AyaPlayerWidget oldWidget) { if (widget.voiceNoteList != oldWidget.voiceNoteList) { - setAudioSource(); + // setAudioSource(); } super.didUpdateWidget(oldWidget); } @@ -126,7 +128,7 @@ class _AyaPlayerWidgetState extends State { builder: (context, snapshot) { final state = snapshot.data; return Text( - state == null ? "" : widget.voiceNoteList[state].userName, + state == null ? "" : widget.voiceNoteList?.elementAt(state)?.userName ?? "", style: TextStyle(fontSize: 10, color: ColorConsts.textGrey1, height: 1), ); }, diff --git a/lib/widgets/text_highlight_widget.dart b/lib/widgets/text_highlight_widget.dart index 6df5211..a537341 100644 --- a/lib/widgets/text_highlight_widget.dart +++ b/lib/widgets/text_highlight_widget.dart @@ -1,4 +1,5 @@ import 'dart:math'; +import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:tangheem/classes/colors.dart'; @@ -10,16 +11,9 @@ class TextHighLightWidget extends StatelessWidget { final TextStyle style; final TextAlign textAlign; final Color highLightColor = ColorConsts.secondaryOrange; + final Function(String) onTap; - TextHighLightWidget({ - Key key, - this.text, - this.textAlign = TextAlign.center, - this.valueText, - this.valueColor, - this.highlights, - this.style = const TextStyle(), - }); + TextHighLightWidget({Key key, this.text, this.textAlign = TextAlign.center, this.valueText, this.valueColor, this.highlights, this.style = const TextStyle(), this.onTap}); @override Widget build(BuildContext context) { @@ -91,9 +85,14 @@ class TextHighLightWidget extends StatelessWidget { TextSpan _highlightSpan(String value) { if (style.color == null) { return TextSpan( - text: value, - style: style.copyWith(color: highLightColor, fontSize: 18), - ); + text: value, + style: style.copyWith(color: highLightColor, fontSize: 18), + recognizer: TapGestureRecognizer() + ..onTap = () { + if (onTap != null) { + onTap(value); + } + }); } else { return TextSpan(text: value, style: style.copyWith(color: valueColor)); }