bookmark feature added & improvements

development
Sikander Saleem 5 years ago
parent 4165e17124
commit 4d793f9416

@ -11,4 +11,5 @@ class GlobalConsts {
static String isRememberMe = "remember_me";
static String email = "email";
static String password = "password";
static String bookmark = "bookmark";
}

@ -2,6 +2,7 @@ import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:tangheem/ui/screens/bookmark_screen.dart';
import 'package:tangheem/ui/screens/contact_us_screen.dart';
import 'ui/common_appbar.dart';
import 'ui/screens/forgot_password_screen.dart';
@ -43,6 +44,9 @@ class Application extends StatelessWidget {
case ContactUsScreen.routeName:
className = CommonAppbar(child: ContactUsScreen());
break;
case BookmarkScreen.routeName:
className = CommonAppbar(child: BookmarkScreen());
break;
case TangheemScreen.routeName:
Map<String, Object> data = settings.arguments;
className = CommonAppbar(
@ -59,8 +63,8 @@ class Application extends StatelessWidget {
);
break;
case QuranScreen.routeName:
String query = settings.arguments.toString();
className = CommonAppbar(child: QuranScreen(query: query));
var bookMark = settings.arguments;
className = CommonAppbar(child: QuranScreen(bookmark: bookMark));
break;
}
return goToNavigation(className);

@ -0,0 +1,56 @@
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:tangheem/classes/consts.dart';
class BookMarkModel {
int surahID;
String surahNameAR;
int ayahID;
int numberInSurah;
int page;
String ayahText;
BookMarkModel({this.surahID, this.surahNameAR, this.ayahID, this.numberInSurah, this.page, this.ayahText});
BookMarkModel.fromJson(Map<String, dynamic> json) {
surahID = json['surahID'];
surahNameAR = json['surahNameAR'];
ayahID = json['ayahID'];
numberInSurah = json['numberInSurah'];
page = json['page'];
ayahText = json['ayah_Text'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['surahID'] = this.surahID;
data['surahNameAR'] = this.surahNameAR;
data['ayahID'] = this.ayahID;
data['numberInSurah'] = this.numberInSurah;
data['page'] = this.page;
data['ayah_Text'] = this.ayahText;
return data;
}
String reverseAyatNumber() {
String _ayaTemp = ayahText.substring(0, ayahText.length - numberInSurah.toString().length);
String _ayaNum = ayahText.substring(ayahText.length - numberInSurah.toString().length, ayahText.length);
_ayaNum = _ayaNum.split('').reversed.join('');
return "$_ayaTemp$_ayaNum";
}
static Future<List<BookMarkModel>> getFromPrefs() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
List encodedList = prefs.getStringList(GlobalConsts.bookmark) ?? [];
return encodedList.map((e) => BookMarkModel.fromJson(jsonDecode(e))).toList();
}
static void saveToPrefs(List<BookMarkModel> list) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
List encodedList = list.map((e) => jsonEncode(e.toJson())).toList();
var abc = await prefs.setStringList(GlobalConsts.bookmark, encodedList);
print("saveToPrefs:$abc");
}
}

@ -5,6 +5,7 @@ import 'package:tangheem/app_state/app_state.dart';
import 'package:tangheem/classes/colors.dart';
import 'package:tangheem/classes/utils.dart';
import 'package:tangheem/models/quick_links_model.dart';
import 'package:tangheem/ui/screens/bookmark_screen.dart';
import 'package:tangheem/ui/screens/contact_us_screen.dart';
import 'package:tangheem/ui/screens/login_screen.dart';
import 'package:tangheem/ui/screens/quran_screen.dart';
@ -126,7 +127,9 @@ class _CommonAppbarState extends State<CommonAppbar> {
children: [
commonIconButton("assets/icons/accessibility.svg", () {}),
commonIconButton("assets/icons/dark_mode.svg", () {}),
commonIconButton("assets/icons/bookmark.svg", () {}),
commonIconButton("assets/icons/bookmark.svg", () {
Navigator.pushNamed(context, BookmarkScreen.routeName);
}),
commonIconButton("assets/icons/increase_size.svg", () {}),
commonIconButton("assets/icons/reduce_size.svg", () {}),
commonIconButton("assets/icons/notification.svg", () {}),
@ -234,8 +237,8 @@ class _CommonAppbarState extends State<CommonAppbar> {
),
),
SizedBox(height: 2),
myListItem("assets/icons/read_quran.svg", "اقرأ القرآن الكريم", false, onTap: () async {
await Navigator.pushNamed(context, QuranScreen.routeName, arguments: "");
myListItem("assets/icons/read_quran.svg", "اقرأ القرآن الكريم", false, onTap: () {
Navigator.pushNamed(context, QuranScreen.routeName, arguments: null);
}),
SizedBox(height: 2),
myListItem("assets/icons/contact.svg", "الاتصال بنا", false, onTap: () {

@ -0,0 +1,127 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:tangheem/classes/colors.dart';
import 'package:tangheem/classes/utils.dart';
import 'package:tangheem/models/bookmark_model.dart';
import 'package:tangheem/models/surah_model.dart';
import 'package:tangheem/ui/misc/no_data_ui.dart';
import 'package:tangheem/ui/screens/quran_screen.dart';
class BookmarkScreen extends StatefulWidget {
static const String routeName = "/bookmark";
final String tangheemQuery;
final String tangheemTypeName;
final SurahModelData surah;
BookmarkScreen({Key key, this.surah, this.tangheemQuery, this.tangheemTypeName}) : super(key: key);
@override
_BookmarkScreenState createState() {
return _BookmarkScreenState();
}
}
class _BookmarkScreenState extends State<BookmarkScreen> {
List<BookMarkModel> _bookMarkList = [];
SlidableController _slidableController;
@override
void initState() {
_slidableController = SlidableController(
onSlideAnimationChanged: handleSlideAnimationChanged,
onSlideIsOpenChanged: handleSlideIsOpenChanged,
);
super.initState();
getBookMark();
}
void handleSlideAnimationChanged(Animation<double> slideAnimation) {
// setState(() {
// _rotationAnimation = slideAnimation;
// });
}
void handleSlideIsOpenChanged(bool isOpen) {
// setState(() {
// _fabColor = isOpen! ? Colors.green : Colors.blue;
// });
}
void getBookMark() async {
Utils.showLoading(context);
_bookMarkList = await BookMarkModel.getFromPrefs();
_bookMarkList = _bookMarkList.reversed.toList();
Utils.hideLoading(context);
setState(() {});
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return _bookMarkList.isEmpty
? NoDataUI()
: ListView.separated(
physics: BouncingScrollPhysics(),
padding: EdgeInsets.all(16),
itemCount: _bookMarkList.length,
separatorBuilder: (context, index) {
return SizedBox(height: 8);
},
itemBuilder: (context, index) {
return Slidable(
controller: _slidableController,
actionPane: SlidableBehindActionPane(),
secondaryActions: <Widget>[
IconSlideAction(
color: Colors.redAccent,
icon: Icons.delete,
closeOnTap: true,
onTap: () {
_bookMarkList.removeAt(index);
BookMarkModel.saveToPrefs(_bookMarkList);
Utils.showToast("تمت إزالة الإشارة المرجعية");
setState(() {});
},
),
],
child: ListTile(
tileColor: Colors.white,
contentPadding: EdgeInsets.fromLTRB(12, 8, 12, 8),
onTap: () {
Navigator.pushNamed(context, QuranScreen.routeName, arguments: _bookMarkList[index]);
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4),
),
title: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
_bookMarkList[index].surahNameAR + ":",
style: TextStyle(fontSize: 12, color: ColorConsts.primaryBlue),
),
Text(
" ${_bookMarkList[index].numberInSurah}",
style: TextStyle(fontSize: 14, color: ColorConsts.secondaryOrange),
),
],
),
subtitle: Text(
_bookMarkList[index].reverseAyatNumber(),
textAlign: TextAlign.start,
style: TextStyle(
fontFamily: "UthmanicHafs",
fontSize: 16,
color: ColorConsts.primaryBlue,
fontWeight: FontWeight.bold,
),
),
),
);
},
);
}
}

@ -1,4 +1,5 @@
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';
@ -8,6 +9,7 @@ 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/bookmark_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';
@ -19,13 +21,12 @@ import 'tangheem_detail_screen.dart';
class QuranScreen extends StatefulWidget {
static const String routeName = "/surah";
final String query;
QuranScreen({Key key, @required this.query}) : super(key: key);
final BookMarkModel bookmark;
QuranScreen({Key key, this.bookmark}) : super(key: key);
@override
_QuranScreenState createState() {
return _QuranScreenState();
return _QuranScreenState(bookmark);
}
}
@ -48,10 +49,13 @@ class _QuranScreenState extends State<QuranScreen> {
List<String> _tangheemWords = [];
_QuranScreenState(this._selectedAyaForBookmark);
@override
void initState() {
super.initState();
scrollToId = ScrollToId(scrollController: scrollController);
getBookMark();
getSurah();
}
@ -65,15 +69,26 @@ class _QuranScreenState extends State<QuranScreen> {
_surahModel = AppState().getSurahModel;
}
_surahList = _surahModel.data.map((element) => element.nameAR).toList();
_currentPage = 1;
_currentPage = widget.bookmark?.page ?? 1;
Utils.hideLoading(context);
//filterData();
} catch (ex, tr) {
Utils.handleException(ex, null);
Utils.hideLoading(context);
Utils.handleException(ex, null);
}
setState(() {});
getQuranByPageNo();
getTangheemBySurahId();
}
List<BookMarkModel> _bookMark = [];
void getBookMark() async {
_bookMark = await BookMarkModel.getFromPrefs();
if (_bookMark.length > 1) {
_selectedAyaForBookmark = _selectedAyaForBookmark ?? _bookMark.last;
}
setState(() {});
}
int numberOfAyah = 0;
@ -90,14 +105,14 @@ class _QuranScreenState extends State<QuranScreen> {
}
void getTangheemBySurahId() async {
Utils.showLoading(context);
//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);
//Utils.hideLoading(context);
}
setState(() {});
//getAyaByRange();
@ -188,9 +203,11 @@ class _QuranScreenState extends State<QuranScreen> {
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 + temp + " ";
});
_surahAya = _surahAya + "\n" + "$_currentPage";
return Container(
padding: EdgeInsets.fromLTRB(16, 24, 16, 0),
width: double.infinity,
@ -241,16 +258,17 @@ class _QuranScreenState extends State<QuranScreen> {
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;
}
}
if (_selectedFromAya < 0) {
Utils.showToast("لم تحدد بداية الآية");
return;
}
if (_selectedToAya < 0) {
Utils.showToast("لم تحدد الآية المنتهية");
return;
}
getAyaByRange();
}),
SizedBox(width: 8),
commonIconButton(
@ -316,41 +334,38 @@ class _QuranScreenState extends State<QuranScreen> {
// style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20, color: ColorConsts.primaryBlue, height: 1),
// ),
// SizedBox(height: 8),
Container(
padding: EdgeInsets.only(left: 4, right: 4),
child:
// Text(
// _surahAya,
// textAlign: TextAlign.center,
// style: TextStyle(
// fontFamily: "UthmanicHafs",
// fontSize: 18,
// color: ColorConsts.primaryBlue,
// fontWeight: FontWeight.bold,
// ),
// ),
// todo "sikander" : lines commented for future
TextHighLightWidget(
text: _surahAya,
valueColor: ColorConsts.primaryBlue,
highLightColor: ColorConsts.primaryBlue,
highlights: _tangheemWords,
onTap: (value) {
List<AyatTangheemTypeMappedData> _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",
fontSize: 18,
fontWeight: FontWeight.bold,
Container(padding: EdgeInsets.only(left: 4, right: 4), child: quranText()
// Text(
// _surahAya,
// textAlign: TextAlign.center,
// style: TextStyle(
// fontFamily: "UthmanicHafs",
// fontSize: 18,
// color: ColorConsts.primaryBlue,
// fontWeight: FontWeight.bold,
// ),
// ),
// todo "sikander" : lines commented for future
// TextHighLightWidget(
// text: _surahAya,
// valueColor: ColorConsts.primaryBlue,
// highLightColor: ColorConsts.primaryBlue,
// highlights: _tangheemWords,
// onTap: (value) {
// List<AyatTangheemTypeMappedData> _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",
// fontSize: 18,
// fontWeight: FontWeight.bold,
// ),
// ),
),
),
),
],
),
),
@ -505,4 +520,122 @@ class _QuranScreenState extends State<QuranScreen> {
),
);
}
BookMarkModel _selectedAyaForBookmark;
Widget quranText() {
List<InlineSpan> 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.reverseAyatNumber();
textSpanList.add(TextSpan(
text: temp + " ",
style: TextStyle(
backgroundColor: _selectedAyaForBookmark?.ayahID == element.ayahID ? ColorConsts.secondaryOrange.withOpacity(.4) : Colors.transparent,
fontFamily: "UthmanicHafs",
fontSize: 18,
color: ColorConsts.primaryBlue,
fontWeight: FontWeight.bold,
),
recognizer: TapGestureRecognizer()
..onTap = () {
setState(() {
if (_selectedAyaForBookmark == null) {
_selectedAyaForBookmark = BookMarkModel.fromJson(element.toJson());
addBookMarkOption();
return;
}
_selectedAyaForBookmark = null;
});
},
));
_surahAya = _surahAya + temp + " ";
});
textSpanList.add(
TextSpan(
text: "\n" + "$_currentPage",
style: TextStyle(
fontFamily: "UthmanicHafs",
fontSize: 18,
color: ColorConsts.primaryBlue,
fontWeight: FontWeight.bold,
),
),
);
_surahAya = _surahAya + "\n" + "$_currentPage";
return RichText(
textAlign: TextAlign.center,
textWidthBasis: TextWidthBasis.parent,
text: TextSpan(
children: textSpanList,
),
);
}
void addBookMarkOption() {
var isAyaHaveTagheem = _ayatTangheemTypeMapped?.data?.firstWhere((element) => element.ayahNo == _selectedAyaForBookmark.ayahID, orElse: () => null);
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: [
if (isAyaHaveTagheem != null)
InkWell(
onTap: () {
Navigator.pop(context);
List<AyatTangheemTypeMappedData> _ayatList = _ayatTangheemTypeMapped.data?.where((element) => element.ayahNo == _selectedAyaForBookmark.ayahID)?.toList() ?? [];
if (_ayatList.length > 1) {
_selectTangheemType(_ayatList);
} else {
Navigator.pushNamed(context, TangheemDetailScreen.routeName, arguments: _ayatList.first);
}
},
child: Row(
children: [Text("عرض تنغيم")],
),
),
if (isAyaHaveTagheem != null) 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("أضف إلى المرجعية")],
),
),
],
),
),
);
});
}
}

@ -15,7 +15,6 @@ import 'package:share/share.dart';
import 'package:tangheem/classes/colors.dart';
import 'package:tangheem/classes/utils.dart';
import 'package:tangheem/models/aya_tangheem_type_mapped.dart';
import 'package:volume_controller/volume_controller.dart';
class AyaPlayerWidget extends StatefulWidget {
final String surahName;
@ -130,7 +129,9 @@ class _AyaPlayerWidgetState extends State<AyaPlayerWidget> {
? null
: DecorationImage(
fit: BoxFit.cover,
image: MemoryImage(base64Decode(widget.voiceNoteList?.elementAt(state)?.profilePicture)),
image: MemoryImage(
base64Decode(widget.voiceNoteList.elementAt(state).profilePicture),
),
),
borderRadius: BorderRadius.all(
Radius.circular(30.0),
@ -190,7 +191,7 @@ class _AyaPlayerWidgetState extends State<AyaPlayerWidget> {
commonIconButton("assets/icons/share_aya.svg", () {
_shareAya();
}),
commonIconButton("assets/icons/bookmark.svg", () {}),
// commonIconButton("assets/icons/bookmark.svg", () {}),
// commonIconButton("assets/icons/audio_level.svg", () async {
// // var vol = await VolumeController.getVolume();
// VolumeController.maxVolume();

@ -12,6 +12,7 @@ class TextHighLightWidget extends StatelessWidget {
final TextAlign textAlign;
final Color highLightColor;
final Function(String) onTap;
final Function(String) onAyaTap;
TextHighLightWidget(
{Key key,
@ -22,7 +23,8 @@ class TextHighLightWidget extends StatelessWidget {
this.highlights,
this.highLightColor = ColorConsts.secondaryOrange,
this.style = const TextStyle(),
this.onTap});
this.onTap,
this.onAyaTap});
@override
Widget build(BuildContext context) {

@ -35,10 +35,10 @@ dependencies:
permission_handler: ^6.1.1
share: ^2.0.1
just_audio: ^0.7.2
volume_controller: ^1.0.1+1
intl: ^0.17.0
shared_preferences: ^2.0.5
url_launcher: ^6.0.3
flutter_slidable: ^0.6.0
dev_dependencies:
flutter_test:

Loading…
Cancel
Save