diff --git a/lib/api/api_client.dart b/lib/api/api_client.dart index 39cb500..b2296a7 100644 --- a/lib/api/api_client.dart +++ b/lib/api/api_client.dart @@ -59,6 +59,7 @@ class ApiClient { _headers.addAll(headers); } print("Url:$url"); + print("body:$jsonObject"); var response = await postJsonForResponse(url, jsonObject, token: token, queryParameters: queryParameters, headers: _headers, retryTimes: retryTimes); try { var jsonData = jsonDecode(response.body); diff --git a/lib/ui/screens/surah_screen.dart b/lib/ui/screens/surah_screen.dart index c0f4a3d..78a4414 100644 --- a/lib/ui/screens/surah_screen.dart +++ b/lib/ui/screens/surah_screen.dart @@ -1,11 +1,14 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; import 'package:flutter_svg/flutter_svg.dart'; 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/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'; @@ -27,7 +30,7 @@ class _SurahScreenState extends State { int _selectedToAya = 0; int _currentPage = 0; - int _ayaInPage = 0; + int _ayaInPage = 5; List _surahList = []; List _fromAyaList = []; List _toAyaList = []; @@ -38,6 +41,7 @@ class _SurahScreenState extends State { @override void initState() { super.initState(); + scrollToId = ScrollToId(scrollController: scrollController); getSurahAndAya(); } @@ -60,19 +64,23 @@ class _SurahScreenState extends State { var filteredAyahList = List.generate(getNextMultiple(numberOfAyah), (index) => index + 1).toList().where((element) => element == 1 || (element % 5) == 0).toList() ?? []; _fromAyaList = filteredAyahList.getRange(0, filteredAyahList.length - 1)?.toList() ?? []; _toAyaList = filteredAyahList.getRange(1, filteredAyahList.length)?.toList() ?? []; + _currentPage = 0; + _selectedFromAya = 0; + _selectedToAya = 0; getAyaByRange(); } void getAyaByRange() async { Utils.showLoading(context); try { - _ayaModel = await TangheemUserApiClient().getAyaByRange(5, 1, _selectedSurah + 1, _fromAyaList[_selectedFromAya], _toAyaList[_selectedToAya]); + _ayaModel = await TangheemUserApiClient().getAyaByRange(_ayaInPage, 1, _selectedSurah + 1, _fromAyaList[_selectedFromAya], _toAyaList[_selectedToAya]); setState(() {}); } catch (ex, tr) { Utils.handleException(ex, null); } finally { Utils.hideLoading(context); } + scrollToId.animateTo("$_currentPage", duration: Duration(milliseconds: 300), curve: Curves.ease); } int getNextMultiple(int num) { @@ -87,6 +95,9 @@ class _SurahScreenState extends State { super.dispose(); } + final ScrollController scrollController = ScrollController(); + ScrollToId scrollToId; + @override Widget build(BuildContext context) { return Container( @@ -118,6 +129,7 @@ class _SurahScreenState extends State { if (_selectedFromAya != index) { _selectedFromAya = index; _selectedToAya = index; + _currentPage = index; getAyaByRange(); } }), @@ -127,6 +139,7 @@ class _SurahScreenState extends State { child: CommonDropDownButton(_selectedToAya, list: _toAyaList.map((e) => "الى الاية" + " $e").toList(), onSelect: (index) { if (_selectedToAya != index) { _selectedToAya = index; + _currentPage = index; getAyaByRange(); } }), @@ -158,8 +171,8 @@ class _SurahScreenState extends State { }), previousOptionButton( "assets/icons/next.svg", - _selectedSurah == (_surahList.length) ? "" : _surahList[_selectedSurah + 1], - _selectedSurah == (_surahList.length) + _selectedSurah == (_surahList.isNotEmpty ? (_surahList.length - 1) : 0) ? "" : _surahList[_selectedSurah + 1], + _selectedSurah == (_surahList.isNotEmpty ? (_surahList.length - 1) : 0) ? null : () { _selectedSurah = _selectedSurah + 1; @@ -181,7 +194,7 @@ class _SurahScreenState extends State { Container( padding: EdgeInsets.only(left: 4, right: 4), child: Text( - _ayaModel?.data?.map((e) => e.ayahText)?.toList()?.reduce((value, element) => value + element) ?? "", + _ayaModel?.data?.map((e) => e.ayahText)?.toList()?.fold("", (value, element) => value + element) ?? "", textAlign: TextAlign.center, style: TextStyle( fontFamily: "UthmanicHafs", @@ -195,23 +208,53 @@ class _SurahScreenState extends State { ), ), SizedBox(height: 8), - Text( - "1 2 3 4 5 6 7 8 9", - style: TextStyle(fontSize: 16, color: ColorConsts.textHintGrey), + AyaScrollViewer( + scrollDirection: Axis.horizontal, + scrollToId: scrollToId, + children: [ + for (int i = 0; i < _fromAyaList.length; i++) + ScrollContent( + id: '$i', + child: Text( + " ${i + 1} ", + style: TextStyle(fontSize: 16, color: _currentPage == i ? ColorConsts.secondaryOrange : ColorConsts.textHintGrey), + ), + ), + ], ), SizedBox(height: 4), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - nextOptionButton("assets/icons/prev_single.svg", "الآيات السابقة", () {}), - previousOptionButton("assets/icons/next_single.svg", "الآيات التالية", () {}), + nextOptionButton( + "assets/icons/prev_single.svg", + "الآيات السابقة", + _currentPage == 0 + ? null + : () { + _currentPage = _currentPage - 1; + _selectedFromAya = _selectedFromAya - 1; + _selectedToAya = _selectedToAya - 1; + getAyaByRange(); + }), + previousOptionButton( + "assets/icons/next_single.svg", + "الآيات التالية", + _currentPage == (_toAyaList.isNotEmpty ? (_toAyaList.length - 1) : 0) + ? null + : () { + _currentPage = _currentPage + 1; + _selectedFromAya = _selectedFromAya + 1; + _selectedToAya = _selectedToAya + 1; + getAyaByRange(); + }), ], ), ], ), ), ), - AyaPlayerWidget() + AyaPlayerWidget(surahName: _surahList.isNotEmpty ? _surahList[_selectedSurah] : null) ], ), ); diff --git a/lib/widgets/auto_scroll_view/aya_scroll_view.dart b/lib/widgets/auto_scroll_view/aya_scroll_view.dart new file mode 100644 index 0000000..687fe67 --- /dev/null +++ b/lib/widgets/auto_scroll_view/aya_scroll_view.dart @@ -0,0 +1,78 @@ +import 'package:flutter/material.dart'; +import 'package:tangheem/widgets/auto_scroll_view/scroll_id.dart'; + +class AyaScrollViewer extends StatefulWidget { + final ScrollToId scrollToId; + final List children; + final Axis scrollDirection; + + AyaScrollViewer({@required this.children, @required this.scrollToId, this.scrollDirection = Axis.vertical}); + + @override + _InteractiveScrollViewerState createState() => _InteractiveScrollViewerState(); +} + +class _InteractiveScrollViewerState extends State { + List _idList = []; + + @override + void initState() { + super.initState(); + setData(); + } + + void setData() { + widget.scrollToId.scrollDirection = widget.scrollDirection; + _idList = []; + widget.scrollToId.scrollContentsList = []; + for (ScrollContent scrollContents in widget.children) { + if (_idList.contains(scrollContents.id)) { + throw Exception('Do not use the same id'); + } else { + _idList.add(scrollContents.id); + } + widget.scrollToId.scrollContentsList.add(ScrollContentWithKey.fromWithout(scrollContents)); + } + } + + @override + void didUpdateWidget(covariant AyaScrollViewer oldWidget) { + if (widget.children != oldWidget.children) { + setData(); + } + super.didUpdateWidget(oldWidget); + } + + @override + Widget build(BuildContext context) { + return SingleChildScrollView( + scrollDirection: widget.scrollDirection, + controller: widget.scrollToId.scrollController, + physics: BouncingScrollPhysics(), + child: buildContent(), + ); + } + + Widget buildContent() { + if (widget.scrollDirection == Axis.vertical) { + return Column( + children: widget.scrollToId.scrollContentsList.map((scrollContents) { + return buildRepaintBoundary(scrollContents); + }).toList(), + ); + } else { + return Row( + children: widget.scrollToId.scrollContentsList.map((scrollContents) { + return buildRepaintBoundary(scrollContents); + }).toList(), + ); + } + } + + RepaintBoundary buildRepaintBoundary(ScrollContentWithKey scrollContents) { + return RepaintBoundary( + key: scrollContents.key, + child: scrollContents.child, + ); + } +} diff --git a/lib/widgets/auto_scroll_view/scroll_id.dart b/lib/widgets/auto_scroll_view/scroll_id.dart new file mode 100644 index 0000000..b84fd48 --- /dev/null +++ b/lib/widgets/auto_scroll_view/scroll_id.dart @@ -0,0 +1,136 @@ +import 'package:flutter/material.dart'; + +class ScrollToId { + final ScrollController scrollController; + List scrollContentsList = []; + Axis scrollDirection; + + ScrollToId({this.scrollController}); + + String idPosition() { + double sumSize = 0; + for (ScrollContentWithKey scrollContents in scrollContentsList) { + if (scrollDirection == Axis.vertical) { + sumSize += scrollContents.key.currentContext.size.height; + } else { + sumSize += scrollContents.key.currentContext.size.width; + } + + if (scrollController.offset < sumSize) { + return scrollContents.id; + } + } + return null; + } + + Future animateTo(String id, {@required Duration duration, @required Curve curve}) async { + Function _function = (double offset) { + scrollController.animateTo(offset, duration: duration, curve: curve); + }; + _scroll(id: id, scrollFunction: _function); + } + + Future jumpTo(String id) async { + Function _function = (double offset) { + scrollController.jumpTo(offset); + }; + _scroll(id: id, scrollFunction: _function); + } + + Future animateToNext({@required Duration duration, @required Curve curve}) async { + Function _function = (double offset) { + scrollController.animateTo(offset, duration: duration, curve: curve); + }; + _scroll(id: _getNextId(number: 1), scrollFunction: _function); + } + + Future jumpToNext() async { + Function _function = (double offset) { + scrollController.jumpTo(offset); + }; + _scroll(id: _getNextId(number: 1), scrollFunction: _function); + } + + Future animateToBefore({@required Duration duration, @required Curve curve}) async { + Function _function = (double offset) { + scrollController.animateTo(offset, duration: duration, curve: curve); + }; + _scroll(id: _getNextId(number: -1), scrollFunction: _function); + } + + Future jumpToBefore() async { + Function _function = (double offset) { + scrollController.jumpTo(offset); + }; + _scroll(id: _getNextId(number: -1), scrollFunction: _function); + } + + String _getNextId({int number}) { + double sumSize = 0; + for (int i = 0; i < scrollContentsList.length; i++) { + if (scrollDirection == Axis.vertical) { + sumSize += scrollContentsList[i].key.currentContext.size.height; + } else { + sumSize += scrollContentsList[i].key.currentContext.size.width; + } + + if (scrollController.offset < sumSize) { + if (number == 1 && i == scrollContentsList.length - 1) return null; + if (number == -1 && i == 0) return null; + + return scrollContentsList[i + number].id; + } + } + return null; + } + + void _scroll({String id, Function scrollFunction}) { + double sumSize = 0; + + for (ScrollContentWithKey scrollContents in scrollContentsList) { + if (scrollContents.id == id) { + try { + if (sumSize < scrollController.position.maxScrollExtent) { + scrollFunction(sumSize); + break; + } else { + scrollFunction(scrollController.position.maxScrollExtent); + break; + } + } catch (e) { + print('$e'); + break; + } + } else { + try { + if (scrollDirection == Axis.vertical) { + sumSize += scrollContents.key.currentContext.size.height; + } else { + sumSize += scrollContents.key.currentContext.size.width; + } + } catch (e) { + print('$e'); + } + } + } + } +} + +class ScrollContent { + final String id; + final Widget child; + + ScrollContent({@required this.id, @required this.child}); +} + +class ScrollContentWithKey { + final Widget child; + final String id; + final GlobalKey key; + + ScrollContentWithKey({this.child, this.key, this.id}); + + factory ScrollContentWithKey.fromWithout(ScrollContent scrollContent) { + return ScrollContentWithKey(child: scrollContent.child, id: scrollContent.id, key: GlobalKey()); + } +} diff --git a/lib/widgets/aya_player_widget.dart b/lib/widgets/aya_player_widget.dart index ebb713f..3a8f246 100644 --- a/lib/widgets/aya_player_widget.dart +++ b/lib/widgets/aya_player_widget.dart @@ -5,7 +5,8 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:tangheem/classes/colors.dart'; class AyaPlayerWidget extends StatefulWidget { - AyaPlayerWidget({Key key}) : super(key: key); + final String surahName; + AyaPlayerWidget({Key key, this.surahName}) : super(key: key); @override _AyaPlayerWidgetState createState() { @@ -68,7 +69,7 @@ class _AyaPlayerWidgetState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "سورة البقسورة", + widget.surahName ?? "سورة البقسورة", maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14, color: ColorConsts.primaryBlack, height: 1),