welcome video player added & improvements.

development
Sikander Saleem 4 years ago
parent e4919cf5d2
commit 5d4dfc529e

@ -39,10 +39,11 @@ android {
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.cloudsolutions.tangheem"
minSdkVersion 16
minSdkVersion 19
targetSdkVersion 29
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
multiDexEnabled true
}
buildTypes {

Binary file not shown.

@ -11,7 +11,7 @@ class AuthenticationApiClient {
factory AuthenticationApiClient() => _instance;
Future<AuthenticationUserModel> authenticateUser(String email, String password) async {
String url = "${ApiConsts.authentication}Login";
String url = "${ApiConsts.authentication}MobileLogin";
var postParams = {"email": email, "password": password};
return await ApiClient().postJsonForObject((json) => AuthenticationUserModel.fromJson(json), url, postParams);
}

@ -60,6 +60,12 @@ class TangheemUserApiClient {
return await ApiClient().postJsonForObject((json) => TangheemType.fromJson(json), url, postParams);
}
Future<AyatTangheemTypeMapped> getAyaTangheemTypeMappedRelated(int surahNo, String ayatNumberInSurahs) async {
String url = "${ApiConsts.tangheemUsers}AyatTangheemTypeMapped_Get";
var postParams = {"surahNo": surahNo, "numberInSurahs": ayatNumberInSurahs};
return await ApiClient().postJsonForObject((json) => AyatTangheemTypeMapped.fromJson(json), url, postParams);
}
Future<AyatTangheemTypeMapped> getAyaTangheemTypeMapped(int surahNo, String tangheemTypeName, String ayaText, int itemsPerPage, int currentPageNo) async {
String url = "${ApiConsts.tangheemUsers}AyatTangheemTypeMapped_Get";
var postParams = {};
@ -78,9 +84,17 @@ class TangheemUserApiClient {
return await ApiClient().postJsonForObject((json) => AyatTangheemTypeMapped.fromJson(json), url, postParams);
}
Future<AyaTangheemType> getAyaTangheemType(int currentPage, int surahNo, String tangheemTypeName) async {
Future<AyaTangheemType> getAyaTangheemType(int surahNo, String tangheemTypeName) async {
String url = "${ApiConsts.tangheemUsers}AyaTangheemType_Get";
var postParams = {"itemsPerPage": 5, "currentPageNo": currentPage, "surahNo": surahNo, "tangheemTypeName": tangheemTypeName};
var postParams = {};
if (surahNo != null) {
postParams["surahNo"] = surahNo;
}
if (tangheemTypeName != null) {
postParams["tangheemTypeName"] = tangheemTypeName;
}
return await ApiClient().postJsonForObject((json) => AyaTangheemType.fromJson(json), url, postParams);
}

@ -19,7 +19,7 @@ class UserApiClient {
String _countryCode,
String _phone,
) async {
String url = "${ApiConsts.user}UserRegistration_Add";
String url = "${ApiConsts.user}MobileUserRegistration_Add";
var postParams = {
"password": _password,
"email": _email,
@ -53,7 +53,7 @@ class UserApiClient {
}
Future<GeneralResponseModel> updatePassword(String _email, int _otp, String _password) async {
String url = "${ApiConsts.user}UpdatePassword";
String url = "${ApiConsts.user}MobileUpdatePassword";
var postParams = {"email": _email, "opt": _otp, "newPassword": _password, "confirmPassword": _password};
return await ApiClient().postJsonForObject((json) => GeneralResponseModel.fromJson(json), url, postParams);
}

@ -1,7 +1,8 @@
class ApiConsts {
//static String baseUrl = "http://10.200.204.20:2801/"; // Local server
static String baseUrl = "http://20.203.25.82"; // Live server
static String baseUrlServices = baseUrl + "/services/"; // Live server
static String baseUrl = "http://20.203.25.82"; // production server
// static String baseUrlServices = baseUrl + "/services/"; // production server
static String baseUrlServices = "https://api.cssynapses.com/tangheem/"; // Live server
static String authentication = baseUrlServices + "api/Authentication/";
static String tangheemUsers = baseUrlServices + "api/TangheemUsers/";
static String adminConfiguration = baseUrlServices + "api/AdminConfiguration/";
@ -14,4 +15,6 @@ class GlobalConsts {
static String password = "password";
static String bookmark = "bookmark";
static String fontZoomSize = "font_zoom_size";
static String welcomeVideoUrl = "welcomeVideoUrl";
static String doNotShowWelcomeVideo = "doNotShowWelcomeVideo";
}

@ -6,9 +6,38 @@ extension EmailValidator on String {
}
String toFormattedDate() {
DateFormat inputFormat = DateFormat('yyyy-mm-ddThh:mm:ss');
DateTime inputDate = inputFormat.parse(this);
DateFormat outputFormat = DateFormat('DD MMMM yyyy hh:mm a');
return outputFormat.format(inputDate);
String date = this.split("T")[0];
String time = this.split("T")[1];
var dates = date.split("-");
return "${dates[2]} ${getMonth(int.parse(dates[1]))} ${dates[0]} ${DateFormat('hh:mm a').format(DateFormat('hh:mm:ss').parse(time))}";
}
getMonth(int month) {
switch (month) {
case 1:
return "January";
case 2:
return "February";
case 3:
return "March";
case 4:
return "April";
case 5:
return "May";
case 6:
return "June";
case 7:
return "July";
case 8:
return "August";
case 9:
return "September";
case 10:
return "October";
case 11:
return "November";
case 12:
return "December";
}
}
}

@ -63,8 +63,11 @@ class Application extends StatelessWidget {
case MemberScreen.routeName:
className = CommonAppbar(child: MemberScreen());
break;
case PdfListScreen.routeName:
className = CommonAppbar(child: PdfListScreen());
break;
case PdfViewerScreen.routeName:
className = CommonAppbar(child: PdfViewerScreen());
className = CommonAppbar(child: PdfViewerScreen(settings.arguments));
break;
case ContentInfoScreen.routeName:
var index = settings.arguments;
@ -97,11 +100,12 @@ class Application extends StatelessWidget {
eventName = eventName.replaceAll("/", "");
if (eventName.isEmpty) eventName = "home";
try {
analytics.setCurrentScreen(
screenName: eventName,
screenClassOverride: eventName,
).then((value) => print("EventSent:$eventName"));
analytics
.setCurrentScreen(
screenName: eventName,
screenClassOverride: eventName,
)
.then((value) => print("EventSent:$eventName"));
} catch (ex) {
print("Analytics:$ex");
}

@ -44,6 +44,8 @@ class AyatTangheemTypeMappedData {
String highlightText;
String userId;
String ayahTextBase;
String ayahNos;
String ayatNumberInSurahs;
List<TangheemProperty> property;
List<VoiceNote> voiceNote;
@ -61,6 +63,8 @@ class AyatTangheemTypeMappedData {
this.highlightText,
this.userId,
this.ayahTextBase,
this.ayahNos,
this.ayatNumberInSurahs,
this.property,
this.voiceNote});
@ -78,6 +82,8 @@ class AyatTangheemTypeMappedData {
highlightText = json['highlightText'];
userId = json['userId'];
ayahTextBase = json['ayahTextBase'];
ayahNos = json['ayahNos'];
ayatNumberInSurahs = json['ayatNumberInSurahs'];
if (json['property'] != null) {
property = [];
json['property'].forEach((v) {
@ -107,6 +113,8 @@ class AyatTangheemTypeMappedData {
data['highlightText'] = this.highlightText;
data['userId'] = this.userId;
data['ayahTextBase'] = this.ayahTextBase;
data['ayahNos'] = this.ayahNos;
data['ayatNumberInSurahs'] = this.ayatNumberInSurahs;
if (this.property != null) {
data['property'] = this.property.map((v) => v.toJson()).toList();
}
@ -133,7 +141,7 @@ class TangheemProperty {
String ayaTangheemTypePropertyId;
String propertyValue;
TangheemProperty({this.tangheemTypePropertyId, this.propertyText, this.isInsideTable, this.textColor,this.orderNo, this.ayaTangheemTypePropertyId, this.propertyValue});
TangheemProperty({this.tangheemTypePropertyId, this.propertyText, this.isInsideTable, this.textColor, this.orderNo, this.ayaTangheemTypePropertyId, this.propertyValue});
TangheemProperty.fromJson(Map<String, dynamic> json) {
tangheemTypePropertyId = json['tangheemTypePropertyId'];

@ -34,6 +34,9 @@ class TangheemTypeData {
String tangheemTypeId;
String tangheemTypeName;
bool isActive;
int orderNo;
String tangheemTypeDescription;
int numberOfAyaTangheemType;
TangheemTypeData({this.tangheemTypeId, this.tangheemTypeName, this.isActive});
@ -41,6 +44,9 @@ class TangheemTypeData {
tangheemTypeId = json['tangheemTypeId'];
tangheemTypeName = json['tangheemTypeName'];
isActive = json['isActive'];
orderNo = json['orderNo'];
tangheemTypeDescription = json['tangheemTypeDescription'];
numberOfAyaTangheemType = json['numberOfAyaTangheemType'];
}
Map<String, dynamic> toJson() {
@ -48,6 +54,9 @@ class TangheemTypeData {
data['tangheemTypeId'] = this.tangheemTypeId;
data['tangheemTypeName'] = this.tangheemTypeName;
data['isActive'] = this.isActive;
data['orderNo'] = this.orderNo;
data['tangheemTypeDescription'] = this.tangheemTypeDescription;
data['numberOfAyaTangheemType'] = this.numberOfAyaTangheemType;
return data;
}
}

@ -6,12 +6,12 @@ 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/content_info_model.dart';
import 'package:tangheem/models/navigation_model.dart';
import 'package:tangheem/models/quick_links_model.dart';
import 'package:tangheem/ui/screens/bookmark_screen.dart';
import 'package:tangheem/ui/screens/content_info_screen.dart';
import 'package:tangheem/ui/screens/login_screen.dart';
import 'package:tangheem/ui/screens/pdf_viewer_screen.dart';
import 'package:url_launcher/url_launcher.dart';
class CommonAppbar extends StatefulWidget {
@ -198,6 +198,9 @@ class _CommonAppbarState extends State<CommonAppbar> {
} else if (subItem.mobileNavigationUrl == "/encyclopedia") {
url = ContentInfoScreen.routeName;
contentId = 1;
} else if (subItem.mobileNavigationUrl == "/tangheempdf") {
url = PdfListScreen.routeName;
contentId = 8;
}
Navigator.pushNamed(context, url, arguments: contentId);
}),
@ -274,7 +277,8 @@ class _CommonAppbarState extends State<CommonAppbar> {
child: Row(
children: [
for (QuickLinksData _quickLink in quickLinks)
commonIconButton(ApiConsts.baseUrl + _quickLink.exposeFilePath, () {
// commonIconButton(ApiConsts.baseUrl + _quickLink.exposeFilePath, () { for live produciton server
commonIconButton( _quickLink.exposeFilePath, () {
_launchURL(_quickLink.imageUrl);
}, size: 35, isAsset: false),
],

@ -99,7 +99,7 @@ class _BookmarkScreenState extends State<BookmarkScreen> {
),
Text(
" ${_bookMarkList[index].numberInSurah}",
style: TextStyle(fontSize: 14, color: ColorConsts.secondaryOrange),
style: TextStyle(fontSize: 14, fontFamily: "BArabics", color: ColorConsts.secondaryOrange),
),
],
),

@ -4,20 +4,25 @@ import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';
import 'package:flutter/services.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_tangheem_type.dart';
import 'package:tangheem/models/content_info_model.dart';
import 'package:tangheem/models/surah_model.dart';
import 'package:tangheem/models/tangheem_type_model.dart';
import 'package:tangheem/ui/dialogs/general_dialog.dart';
import 'package:tangheem/ui/screens/tangheem_screen.dart';
import 'package:tangheem/widgets/common_dropdown_button.dart';
import 'package:tangheem/widgets/video_player_widget.dart';
class HomeScreen extends StatefulWidget {
static const String routeName = "/";
final FirebaseAnalytics analytics;
HomeScreen(this.analytics, {Key key}) : super(key: key);
@override
@ -68,22 +73,94 @@ class _HomeScreenState extends State<HomeScreen> {
checkScreenMode();
}
void filterTangheemTypesListBySurah(int surahNo, {bool showLoading = true}) async {
if (showLoading) Utils.showLoading(context);
try {
AyaTangheemType ayaTangheemType = await TangheemUserApiClient().getAyaTangheemType(surahNo, null);
var tangheemType = _tangheemType?.data?.where((element) => element.isActive)?.toList() ?? [];
var ayaTangheem = ayaTangheemType?.data?.where((element) => element.isActive)?.toList() ?? [];
var result = tangheemType.where((tangheem) => ayaTangheem.any((element) => tangheem.tangheemTypeId == element.tangheemTypeId)).toList() ?? [];
_tangheemListNotifier.value = result?.map((element) => element.tangheemTypeName)?.toList() ?? [];
if (showLoading) Utils.hideLoading(context);
} catch (ex) {
if (showLoading) Utils.hideLoading(context);
Utils.handleException(ex, null);
}
}
void filterSurahListByTangheemType(String tangheemName) async {
Utils.showLoading(context);
try {
AyaTangheemType ayaTangheemType = await TangheemUserApiClient().getAyaTangheemType(null, tangheemName);
_surahList = _surahModel.data.where((surah) => ayaTangheemType.data.any((element) => surah.id == element.surahNo)).toList().map((element) => element.nameAR).toList();
setState(() {});
Utils.hideLoading(context);
} catch (ex) {
Utils.hideLoading(context);
Utils.handleException(ex, null);
}
}
void checkScreenMode() {
WidgetsBinding.instance.addPostFrameCallback((_) {
WidgetsBinding.instance.addPostFrameCallback((_) async {
if (MediaQuery.of(context).orientation == Orientation.portrait) {
showDialog(
await showDialog(
context: context,
barrierColor: ColorConsts.secondaryWhite.withOpacity(0.8),
builder: (BuildContext context) => GeneralDialog(),
);
}
showWelcomeVideoDialog();
});
}
SharedPreferences prefs;
void showWelcomeVideoDialog() async {
prefs = await SharedPreferences.getInstance();
String permLink = "aAmP-WcI6dg";
String link = prefs.getString(GlobalConsts.welcomeVideoUrl) ?? permLink;
if (permLink == link) {
await prefs.setString(GlobalConsts.welcomeVideoUrl, permLink);
bool showDialog = prefs.getBool(GlobalConsts.doNotShowWelcomeVideo) ?? false;
if (showDialog) {
return;
}
} else {
await prefs.setString(GlobalConsts.welcomeVideoUrl, permLink);
}
await prefs.setBool(GlobalConsts.doNotShowWelcomeVideo, false);
showDialog(
context: context,
barrierColor: ColorConsts.secondaryWhite.withOpacity(0.8),
builder: (BuildContext context) => VideoPlayerWidget(permLink),
);
}
Future<void> getTangheemTypes() async {
try {
_tangheemType = await TangheemUserApiClient().getTangheemType();
if ((_tangheemType?.data?.length ?? 0) > 0) {
_tangheemType.data.sort((a, b) => a.orderNo.compareTo(b.orderNo));
}
_tangheemListNotifier.value = _tangheemType?.data?.where((element) => element.isActive)?.toList()?.map((element) => element.tangheemTypeName)?.toList() ?? [];
return;
// enable these lines if in future need to filter types too
if (_surahModel.data.map((element) => element.nameAR).toList().length == _surahList.length && _selectedSurah >= 0) {
setState(() {
_selectedTangheemType = -1;
});
// filterTangheemTypesListBySurah(_surahModel.data[_selectedSurah].id, showLoading: false);
} else {
if (_surahModel.data.map((element) => element.nameAR).toList().length != _surahList.length && _selectedSurah >= 0) {
setState(() {
_selectedSurah = -1;
});
}
_tangheemListNotifier.value = _tangheemType?.data?.where((element) => element.isActive)?.toList()?.map((element) => element.tangheemTypeName)?.toList() ?? [];
}
} catch (ex) {}
}
@ -126,9 +203,14 @@ class _HomeScreenState extends State<HomeScreen> {
builder: (context, value, child) {
return CommonDropDownButton(_selectedTangheemType, hintText: "اختر الأسلوب اللغوي", list: value, onSelect: (index) {
if (_selectedTangheemType != index) {
setState(() {
setState((){
_selectedSurah = -1;
_selectedTangheemType = index;
});
if (_selectedSurah >= 0) {
return;
}
filterSurahListByTangheemType(_tangheemListNotifier.value[_selectedTangheemType]);
}
});
},
@ -141,64 +223,64 @@ class _HomeScreenState extends State<HomeScreen> {
setState(() {
_selectedSurah = index;
});
if (_selectedTangheemType >= 0) {
return;
}
// filterTangheemTypesListBySurah(_surahModel.data[_selectedSurah].id);
}
}),
)
],
),
SizedBox(height: 16),
InkWell(
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
onTap: () async {
if (_selectedTangheemType < 0) {
Utils.showToast("الرجائ تعبئة جميع القوائم");
return;
}
if (_selectedSurah < 0) {
Utils.showToast("الرجائ تعبئة جميع القوائم");
return;
}
_searchFocusNode.unfocus();
_searchFocusNode.canRequestFocus = false;
var data = {"tangheemTypeName": _tangheemListNotifier.value[_selectedTangheemType], "surahData": _surahModel.data[_selectedSurah]};
try {
await widget.analytics.logEvent(
name: 'tangheem_by_selection',
parameters: <String, dynamic>{
"tangheemTypeName": _tangheemListNotifier.value[_selectedTangheemType],
"surahName": _surahModel.data[_selectedSurah].nameAR,
},
);
} catch (ex) {
print("tangheemTypeName:$ex");
}
await Navigator.pushNamed(context, TangheemScreen.routeName, arguments: data);
_searchFocusNode.canRequestFocus = true;
getTangheemTypes();
},
child: Container(
height: 36,
decoration: BoxDecoration(
color: 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(
"بحث",
maxLines: 1,
style: TextStyle(fontSize: 12, color: Colors.white),
),
SizedBox(width: 12),
SvgPicture.asset("assets/icons/go_forward.svg", width: 20, height: 20, color: Colors.white),
],
),
),
Row(
children: [
iconButton("بحث", "assets/icons/go_forward.svg", () async {
// if (_selectedTangheemType < 0) {
// Utils.showToast("الرجائ تعبئة جميع القوائم");
// return;
// }
if (_selectedSurah < 0) {
Utils.showToast("يرجى اختيار السورة");
return;
}
_searchFocusNode.unfocus();
_searchFocusNode.canRequestFocus = false;
var surah = _surahModel.data.firstWhere((surah) => surah.nameAR == _surahList[_selectedSurah], orElse: null);
Map<String, Object> data = {};
data["surahData"] = surah;
if (_selectedTangheemType >= 0) {
data["tangheemTypeName"] = _tangheemListNotifier.value[_selectedTangheemType].toString();
}
try {
await widget.analytics.logEvent(
name: 'tangheem_by_selection',
parameters: <String, dynamic>{
"tangheemTypeName": _tangheemListNotifier.value[_selectedTangheemType],
"surahName": _surahModel.data[_selectedSurah].nameAR,
},
);
} catch (ex) {
print("tangheemTypeName:$ex");
}
await Navigator.pushNamed(context, TangheemScreen.routeName, arguments: data);
_searchFocusNode.canRequestFocus = true;
await getTangheemTypes();
}),
SizedBox(width: 8),
iconButton(
"إلغاء",
"assets/icons/cancel.svg",
(_selectedSurah == -1 && _selectedTangheemType == -1)
? null
: () {
_selectedSurah = -1;
_selectedTangheemType = -1;
_surahList = _surahModel.data.map((element) => element.nameAR).toList();
_tangheemListNotifier.value = _tangheemType?.data?.where((element) => element.isActive)?.toList()?.map((element) => element.tangheemTypeName)?.toList() ?? [];
setState(() {});
}),
],
),
SizedBox(height: 16),
Container(
@ -236,7 +318,7 @@ class _HomeScreenState extends State<HomeScreen> {
);
await Navigator.pushNamed(context, TangheemScreen.routeName, arguments: data);
_searchFocusNode.canRequestFocus = true;
getTangheemTypes();
await getTangheemTypes();
},
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
@ -265,4 +347,34 @@ class _HomeScreenState extends State<HomeScreen> {
),
);
}
Widget iconButton(String title, String icon, VoidCallback callback) {
return InkWell(
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
onTap: callback,
child: Container(
height: 36,
decoration: BoxDecoration(
color: callback == null ? ColorConsts.textHintGrey : 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(icon, width: 20, height: 20, color: Colors.white),
],
),
),
);
}
}

@ -1,10 +1,88 @@
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_pdfviewer/pdfviewer.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/content_info_model.dart';
import 'package:tangheem/ui/misc/no_data_ui.dart';
class PdfViewerScreen extends StatefulWidget {
class PdfListScreen extends StatefulWidget {
static const String routeName = "/tangheem_pdf";
PdfViewerScreen({Key key}) : super(key: key);
PdfListScreen({Key key}) : super(key: key);
@override
_PdfListScreenState createState() {
return _PdfListScreenState();
}
}
class _PdfListScreenState extends State<PdfListScreen> {
List<ContentInfoDataModel> contentList;
@override
void initState() {
super.initState();
getPdfs();
}
void getPdfs() async {
Utils.showLoading(context);
try {
var membersData = await TangheemUserApiClient().getContentInfo(8);
contentList = membersData?.data ?? [];
} catch (ex) {
contentList = [];
Utils.handleException(ex, null);
} finally {
Utils.hideLoading(context);
}
setState(() {});
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return contentList == null
? SizedBox()
: contentList.isEmpty
? NoDataUI()
: ListView.separated(
physics: BouncingScrollPhysics(),
padding: EdgeInsets.all(16),
itemCount: contentList.length,
separatorBuilder: (context, index) {
return SizedBox(height: 8);
},
itemBuilder: (context, index) {
return ListTile(
tileColor: Colors.white,
onTap: () {
Navigator.pushNamed(context, PdfViewerScreen.routeName, arguments: contentList[index]);
},
title: Text(
contentList[index].fileName?.trim() ?? "",
style: TextStyle(fontSize: 14, color: ColorConsts.primaryBlue),
),
subtitle: Text(
contentList[index].contentTypeNameAr?.trim() ?? "",
style: TextStyle(fontSize: 12, color: ColorConsts.primaryBlue),
),
);
},
);
}
}
class PdfViewerScreen extends StatefulWidget {
static const String routeName = "/tangheem_pdf_view";
final ContentInfoDataModel pdfDetail;
PdfViewerScreen(this.pdfDetail, {Key key}) : super(key: key);
@override
_PdfViewerScreenState createState() {
@ -27,8 +105,8 @@ class _PdfViewerScreenState extends State<PdfViewerScreen> {
@override
Widget build(BuildContext context) {
return SfPdfViewer.asset(
'assets/files/tangheem.pdf',
return SfPdfViewer.network(
widget.pdfDetail.exposeFilePath,
key: _pdfViewerKey,
canShowScrollHead: false,
enableTextSelection: false,

@ -85,7 +85,7 @@ class _QuranScreenState extends State<QuranScreen> {
}
setState(() {});
getQuranByPageNo();
getTangheemBySurahId();
// getTangheemBySurahId();
}
List<BookMarkModel> _bookMark = [];
@ -111,7 +111,7 @@ class _QuranScreenState extends State<QuranScreen> {
setState(() {});
}
void getTangheemBySurahId() async {
Future getTangheemBySurahId() async {
try {
_ayatTangheemTypeMapped = await TangheemUserApiClient().getTangheemBySurah(_selectedSurah + 1);
_tangheemWords = _ayatTangheemTypeMapped?.data?.map((e) => e.highlightText)?.toList() ?? [];
@ -125,20 +125,22 @@ class _QuranScreenState extends State<QuranScreen> {
Utils.showLoading(context);
try {
_ayaModel = await TangheemUserApiClient().getAyaByFilter(_selectedSurah + 1, _fromAyaList[_selectedFromAya], _toAyaList[_selectedToAya]);
await getTangheemBySurahId();
} catch (ex) {
Utils.handleException(ex, null);
} finally {
Utils.hideLoading(context);
}
getTangheemBySurahId();
// getTangheemBySurahId();
}
void getQuranByPageNo() async {
Utils.showLoading(context);
try {
_ayaModel = await TangheemUserApiClient().getQuranByPageNo(_currentPage);
await getTangheemBySurahId();
Utils.hideLoading(context);
setState(() {});
// setState(() {});
} catch (ex) {
Utils.handleException(ex, null);
Utils.hideLoading(context);
@ -322,29 +324,30 @@ class _QuranScreenState extends State<QuranScreen> {
),
quranTextView,
SizedBox(height: 4),
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 (_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();
}),
],
),
],
),
);
@ -516,7 +519,7 @@ class _QuranScreenState extends State<QuranScreen> {
TextSpan(
text: "\n" + "$_currentPage",
style: TextStyle(
fontFamily: "UthmanicHafs",
fontFamily: "BArabics",
fontSize: fontSize,
color: ColorConsts.primaryBlue,
fontWeight: FontWeight.bold,
@ -559,8 +562,7 @@ class _QuranScreenState extends State<QuranScreen> {
onTap: () async {
Navigator.pop(context);
List<AyatTangheemTypeMappedData> list = [];
list = _ayatTangheemTypeMapped?.data?.where((element) => element.ayahNo == _selectedAyaForBookmark.ayahID)?.toList() ?? [];
list = _ayatTangheemTypeMapped?.data?.where((element) => int.parse(element.ayahNos.split(",")[0]) == _selectedAyaForBookmark.ayahID)?.toList() ?? [];
if (list.isEmpty) {
Utils.showToast("لا توجد أساليب تنغيم في هذه الآية");
return;
@ -610,5 +612,6 @@ class _QuranScreenState extends State<QuranScreen> {
class TangheemTemp {
final String tangheemName;
final String ayaTangheemId;
TangheemTemp(this.tangheemName, this.ayaTangheemId);
}

@ -1,5 +1,6 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:tangheem/api/admin_configuration_api_client.dart';
@ -21,6 +22,7 @@ import 'login_screen.dart';
class TangheemDetailParams {
final String selectedTangheemTypeId;
final List<AyatTangheemTypeMappedData> ayatTangheemTypeMappedDataList;
TangheemDetailParams({@required this.selectedTangheemTypeId, @required this.ayatTangheemTypeMappedDataList});
}
@ -43,6 +45,8 @@ class _TangheemDetailScreenState extends State<TangheemDetailScreen> {
List<AyatTangheemTypeMappedData> ayatTangheemTypeMappedDataList = [];
List<AyatTangheemTypeMappedData> _dataList = [];
int _discussionPage = -1;
AyatTangheemTypeMappedData _ayatTangheemTypeMappedFirstData;
DiscussionModel _discussionModel;
@ -52,12 +56,11 @@ class _TangheemDetailScreenState extends State<TangheemDetailScreen> {
@override
void initState() {
super.initState();
ayatTangheemTypeMappedDataList = widget.tangheemDetailParams.ayatTangheemTypeMappedDataList;
_ayatTangheemTypeMappedFirstData = ayatTangheemTypeMappedDataList.first;
filterVoiceListData();
getPrefs();
getTangheemDiscussion();
getTangheemDiscussionAndRelatedData();
}
double fontSize = 18;
@ -85,18 +88,42 @@ class _TangheemDetailScreenState extends State<TangheemDetailScreen> {
return "";
}
void getTangheemDiscussion() async {
void getTangheemDiscussionAndRelatedData() async {
Utils.showLoading(context);
try {
_discussionModel = await TangheemUserApiClient().getDiscussionByTangheemID(_discussionPage, widget.tangheemDetailParams.selectedTangheemTypeId);
if (!_ayatTangheemTypeMappedFirstData.ayatNumberInSurahs.contains(",")) {
_dataList = await getTangheemRelatedData();
}
Utils.hideLoading(context);
setState(() {});
} catch (ex) {
print(ex);
Utils.handleException(ex, null);
Utils.hideLoading(context);
}
}
Future<List<AyatTangheemTypeMappedData>> getTangheemRelatedData() async {
_dataList = [];
AyatTangheemTypeMapped _ayatTangheemTypeMapped =
await TangheemUserApiClient().getAyaTangheemTypeMappedRelated(_ayatTangheemTypeMappedFirstData.surahNo, _ayatTangheemTypeMappedFirstData.ayatNumberInSurahs);
_dataList = _ayatTangheemTypeMapped?.data ?? [];
if (_dataList.isNotEmpty) {
_dataList = _dataList.where((element) => element.tangheemTypeId != _ayatTangheemTypeMappedFirstData.tangheemTypeId)?.toList() ?? [];
var _tempList = _dataList.map((e) => e.tangheemTypeId).toList().toSet().toList();
var _dataTempList = <AyatTangheemTypeMappedData>[];
_tempList.forEach((_tempElement) {
_dataTempList.add(_dataList.firstWhere((element) {
return !element.ayatNumberInSurahs.contains(",") && (element.tangheemTypeId == _tempElement);
}, orElse: null));
});
_dataList = _dataTempList;
}
return _dataList;
}
void sendComment(String discussionText) async {
Utils.showLoading(context);
try {
@ -264,19 +291,29 @@ class _TangheemDetailScreenState extends State<TangheemDetailScreen> {
SizedBox(width: 4),
Expanded(
child: Container(
height: 40,
padding: EdgeInsets.only(left: 4, right: 8),
alignment: Alignment.centerRight,
child: Text(
_tangheemAboveTableList[index].propertyValue,
maxLines: 1,
style: TextStyle(
color: Color(
Utils.stringToHex(_tangheemAboveTableList[index].textColor),
),
color: ColorConsts.secondaryWhite,
padding: EdgeInsets.all(4),
child: Container(
color: Colors.white,
padding: EdgeInsets.only(left: 4, right: 8),
// alignment: Alignment.centerRight,
child: Html(
data: _tangheemAboveTableList[index]?.propertyValue ?? "",
style: {
'html': Style(textAlign: TextAlign.left),
},
),
// Text(
// _tangheemAboveTableList[index].propertyValue,
// maxLines: 1,
// style: TextStyle(
// color: Color(
// Utils.stringToHex(_tangheemAboveTableList[index].textColor),
// ),
// ),
// ),
),
color: ColorConsts.secondaryWhite,
),
)
],
@ -308,6 +345,60 @@ class _TangheemDetailScreenState extends State<TangheemDetailScreen> {
),
SizedBox(height: 8),
discussionView(_discussionModel?.data ?? []),
if (_dataList.isNotEmpty)
Container(
margin: EdgeInsets.only(top: 8),
padding: EdgeInsets.only(bottom: 20),
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
),
child: Column(
children: [
Container(
height: 60,
width: double.infinity,
margin: EdgeInsets.only(bottom: 8),
alignment: Alignment.center,
decoration: BoxDecoration(
color: ColorConsts.primaryBlue,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(8),
topRight: Radius.circular(8),
),
),
child: Text(
"قائمة الأساليب اللغوية في هذه الآية",
style: TextStyle(fontSize: 16, color: Colors.white),
),
),
ListView.separated(
padding: EdgeInsets.fromLTRB(4, 8, 4, 4),
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: _dataList.length,
separatorBuilder: (context, index) => SizedBox(height: 16),
itemBuilder: (context, index) {
return InkWell(
onTap: () {
List<AyatTangheemTypeMappedData> list = _dataList;
var removedData = list[index];
list.remove(removedData);
list.insert(0, removedData);
TangheemDetailParams tangheem = TangheemDetailParams(selectedTangheemTypeId: _dataList[index].ayaTangheemTypeId, ayatTangheemTypeMappedDataList: list);
Navigator.pushNamed(context, TangheemDetailScreen.routeName, arguments: tangheem);
},
child: Text(
_dataList[index].tangheemTypeName,
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16, color: ColorConsts.secondaryOrange, height: 1.5),
),
);
},
),
],
),
),
SizedBox(height: 16),
AyaRecordWidget()
],
@ -434,19 +525,28 @@ class _TangheemDetailScreenState extends State<TangheemDetailScreen> {
SizedBox(width: 4),
Expanded(
child: Container(
height: 40,
padding: EdgeInsets.only(left: 4, right: 8),
alignment: Alignment.centerRight,
child: Text(
tangheemPropertyList[index].propertyValue,
maxLines: 1,
style: TextStyle(
color: Color(
Utils.stringToHex(tangheemPropertyList[index].textColor),
),
color: ColorConsts.secondaryWhite,
padding: EdgeInsets.all(4),
child: Container(
color: Colors.white,
padding: EdgeInsets.only(left: 4, right: 8),
// alignment: Alignment.centerRight,
child: Html(
data: tangheemPropertyList[index]?.propertyValue ?? "",
style: {
'html': Style(textAlign: TextAlign.left),
},
),
// Text(
// tangheemPropertyList[index].propertyValue,
// maxLines: 1,
// style: TextStyle(
// color: Color(
// Utils.stringToHex(tangheemPropertyList[index].textColor),
// ),
// ),
// ),
),
color: ColorConsts.secondaryWhite,
),
)
],
@ -473,32 +573,41 @@ class _TangheemDetailScreenState extends State<TangheemDetailScreen> {
children: [
Container(
color: ColorConsts.secondaryWhite,
height: 30,
alignment: Alignment.centerRight,
//height: 30,
alignment: Alignment.center,
padding: EdgeInsets.only(left: 2, right: 4),
width: double.infinity,
child: Text(
property.propertyText ?? "",
maxLines: 1,
// maxLines: 1,
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 12, color: ColorConsts.secondaryOrange),
),
),
Container(width: double.infinity, height: 4, color: Colors.white),
Container(
color: ColorConsts.secondaryWhite,
height: 30,
padding: EdgeInsets.only(left: 2, right: 4),
alignment: Alignment.centerRight,
width: double.infinity,
child: Text(
property.propertyValue ?? "",
maxLines: 1,
style: TextStyle(
fontSize: 12,
color: Color(
Utils.stringToHex(property.textColor),
),
padding: EdgeInsets.all(4),
child: Container(
color: Colors.white,
padding: EdgeInsets.only(left: 2, right: 4),
width: double.infinity,
child: Html(
data: property.propertyValue ?? "",
style: {
'html': Style(textAlign: TextAlign.left),
},
),
// Text(
// property.propertyValue ?? "",
// maxLines: 1,
// style: TextStyle(
// fontSize: 12,
// color: Color(
// Utils.stringToHex(property.textColor),
// ),
// ),
// ),
),
),
],
@ -553,6 +662,7 @@ class _TangheemDetailScreenState extends State<TangheemDetailScreen> {
}
Widget discussionView(List<DiscussionModelData> _discussionList) {
_discussionList = _discussionList.where((element) => element.status.toLowerCase() == "Accept".toLowerCase()).toList();
return Stack(
alignment: Alignment.bottomCenter,
children: [
@ -589,7 +699,7 @@ class _TangheemDetailScreenState extends State<TangheemDetailScreen> {
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"تعليق على الآية ${_ayatTangheemTypeMappedFirstData.ayatNumberInSurah}",
"تعليق على الآية ${_ayatTangheemTypeMappedFirstData.ayatNumberInSurahs}",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16, color: ColorConsts.primaryBlue, height: 1.5),
),
SizedBox(height: 4),

@ -85,9 +85,12 @@ class _TangheemScreenState extends State<TangheemScreen> {
itemBuilder: (context, index) {
return InkWell(
onTap: () {
List<AyatTangheemTypeMappedData> list = [];
list = _dataList?.where((element) => (element.ayahNo == _dataList[index].ayahNo) && (element.tangheemTypeId == _dataList[index].tangheemTypeId))?.toList() ?? [];
TangheemDetailParams tangheem = TangheemDetailParams(selectedTangheemTypeId: _dataList[index].ayaTangheemTypeId, ayatTangheemTypeMappedDataList: list);
List<AyatTangheemTypeMappedData> list = <AyatTangheemTypeMappedData>[] + _dataList;
var removedData = _dataList[index];
list.remove(removedData);
list.insert(0, removedData);
list = list?.where((element) => (element.ayahNos.contains(removedData.ayahNos)) && (element.tangheemTypeId == removedData.tangheemTypeId))?.toList() ?? [];
TangheemDetailParams tangheem = TangheemDetailParams(selectedTangheemTypeId: removedData.ayaTangheemTypeId, ayatTangheemTypeMappedDataList: list);
Navigator.pushNamed(context, TangheemDetailScreen.routeName, arguments: tangheem);
},
borderRadius: BorderRadius.circular(4),
@ -110,8 +113,8 @@ class _TangheemScreenState extends State<TangheemScreen> {
style: TextStyle(fontSize: 12, color: ColorConsts.primaryBlue),
),
Text(
" ${_dataList[index].ayatNumberInSurah}",
style: TextStyle(fontSize: 14, color: ColorConsts.secondaryOrange),
" ${_dataList[index].ayatNumberInSurahs.split(",").toList().reversed.join(",")}",
style: TextStyle(fontSize: 14, fontFamily: "BArabics", color: ColorConsts.secondaryOrange),
),
],
),

@ -85,12 +85,12 @@ class _AyaPlayerWidgetState extends State<AyaPlayerWidget> {
if (_tempIndex == null || _tempIndex != index) {
_tempIndex = index;
String encodedImage = widget.voiceNoteList.elementAt(index).profilePicture;
if (encodedImage.contains("data:image/png;base64,")) {
if (encodedImage?.contains("data:image/png;base64,") ?? false) {
encodedImage = encodedImage.replaceAll("data:image/png;base64,", "");
}
} if (encodedImage == null) return null;
temp = base64Decode(encodedImage);
}
if (temp == null) return null;
return DecorationImage(
fit: BoxFit.cover,
image: MemoryImage(temp),
@ -139,35 +139,36 @@ class _AyaPlayerWidgetState extends State<AyaPlayerWidget> {
});
},
),
StreamBuilder<int>(
stream: _player.currentIndexStream,
builder: (context, snapshot) {
int state = snapshot.data;
if (state == null) return SizedBox();
return Container(
width: 50.0,
margin: EdgeInsets.only(left: 8, right: 8),
height: 50.0,
decoration: BoxDecoration(
image: widget.voiceNoteList.length < 1 ? null : getDecodedImage(state),
borderRadius: BorderRadius.all(
Radius.circular(30.0),
if ((widget.voiceNoteList?.length ?? 0) > 0)
StreamBuilder<int>(
stream: _player.currentIndexStream,
builder: (context, snapshot) {
int state = snapshot.data;
if (state == null) return SizedBox();
return Container(
width: 50.0,
margin: EdgeInsets.only(left: 8, right: 8),
height: 50.0,
decoration: BoxDecoration(
image: widget.voiceNoteList.length < 1 ? null : getDecodedImage(state),
borderRadius: BorderRadius.all(
Radius.circular(30.0),
),
),
),
child: widget.voiceNoteList.length < 1
? ClipRRect(
borderRadius: BorderRadius.all(
Radius.circular(30.0),
),
child: SvgPicture.asset(
"assets/icons/chat_user.svg",
clipBehavior: Clip.antiAlias,
),
)
: null,
);
},
),
child: widget.voiceNoteList.length < 1
? ClipRRect(
borderRadius: BorderRadius.all(
Radius.circular(30.0),
),
child: SvgPicture.asset(
"assets/icons/chat_user.svg",
clipBehavior: Clip.antiAlias,
),
)
: null,
);
},
),
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
@ -180,16 +181,17 @@ class _AyaPlayerWidgetState extends State<AyaPlayerWidget> {
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14, color: ColorConsts.primaryBlack, height: 1),
),
SizedBox(height: 4),
StreamBuilder<int>(
stream: _player.currentIndexStream,
builder: (context, snapshot) {
final state = snapshot.data;
return Text(
(state == null || widget.voiceNoteList.isEmpty) ? "" : widget.voiceNoteList?.elementAt(state)?.userName ?? "",
style: TextStyle(fontSize: 10, color: ColorConsts.textGrey1, height: 1),
);
},
),
if ((widget.voiceNoteList?.length ?? 0) > 0)
StreamBuilder<int>(
stream: _player.currentIndexStream,
builder: (context, snapshot) {
final state = snapshot.data;
return Text(
(state == null || widget.voiceNoteList.isEmpty) ? "" : widget.voiceNoteList?.elementAt(state)?.userName ?? "",
style: TextStyle(fontSize: 10, color: ColorConsts.textGrey1, height: 1),
);
},
),
],
),
),
@ -234,80 +236,81 @@ class _AyaPlayerWidgetState extends State<AyaPlayerWidget> {
],
),
SizedBox(height: 8),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
commonIconButton("assets/icons/next_aya.svg", () {
_player.seekToNext();
}),
SizedBox(width: 4),
StreamBuilder<PlayerState>(
stream: _player.playerStateStream,
builder: (context, snapshot) {
final state = snapshot.data?.playing ?? false;
if (state) {
if (_player?.duration?.inSeconds == _player?.position?.inSeconds) {
_player.pause();
_player.seek(Duration.zero);
if ((widget.voiceNoteList?.length ?? 0) > 0)
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
commonIconButton("assets/icons/next_aya.svg", () {
_player.seekToNext();
}),
SizedBox(width: 4),
StreamBuilder<PlayerState>(
stream: _player.playerStateStream,
builder: (context, snapshot) {
final state = snapshot.data?.playing ?? false;
if (state) {
if (_player?.duration?.inSeconds == _player?.position?.inSeconds) {
_player.pause();
_player.seek(Duration.zero);
}
}
}
return commonIconButton(state ? "assets/icons/pause.svg" : "assets/icons/play_aya.svg", () {
state
? _player.pause()
: _isAudioHaveError
? Utils.showToast("خطأ في تحميل ملف الصوت")
: _player.play();
});
},
),
SizedBox(width: 4),
commonIconButton("assets/icons/previous_aya.svg", () {
_player.seekToPrevious();
}),
SizedBox(width: 16),
Expanded(
child: StreamBuilder<Duration>(
return commonIconButton(state ? "assets/icons/pause.svg" : "assets/icons/play_aya.svg", () {
state
? _player.pause()
: _isAudioHaveError
? Utils.showToast("خطأ في تحميل ملف الصوت")
: _player.play();
});
},
),
SizedBox(width: 4),
commonIconButton("assets/icons/previous_aya.svg", () {
_player.seekToPrevious();
}),
SizedBox(width: 16),
Expanded(
child: StreamBuilder<Duration>(
stream: _player.positionStream,
builder: (context, snapshot) {
final state = snapshot.data;
return SliderTheme(
data: SliderTheme.of(context).copyWith(
inactiveTrackColor: ColorConsts.sliderBackground,
activeTrackColor: ColorConsts.secondaryOrange,
trackHeight: 8.0,
thumbColor: ColorConsts.primaryBlack,
thumbShape: RoundSliderThumbShape(enabledThumbRadius: 10.0),
overlayColor: ColorConsts.primaryBlack.withAlpha(32),
overlayShape: RoundSliderOverlayShape(overlayRadius: 12.0),
),
child: Directionality(
textDirection: TextDirection.ltr,
child: Slider(
value: (state?.inSeconds ?? 0) + 0.0,
min: 0,
max: (_player?.duration?.inSeconds ?? 0) + 0.0,
onChanged: (value) {
_player.seek(Duration(seconds: value.round()));
},
),
),
);
},
),
),
SizedBox(width: 8),
StreamBuilder<Duration>(
stream: _player.positionStream,
builder: (context, snapshot) {
final state = snapshot.data;
return SliderTheme(
data: SliderTheme.of(context).copyWith(
inactiveTrackColor: ColorConsts.sliderBackground,
activeTrackColor: ColorConsts.secondaryOrange,
trackHeight: 8.0,
thumbColor: ColorConsts.primaryBlack,
thumbShape: RoundSliderThumbShape(enabledThumbRadius: 10.0),
overlayColor: ColorConsts.primaryBlack.withAlpha(32),
overlayShape: RoundSliderOverlayShape(overlayRadius: 12.0),
),
child: Directionality(
textDirection: TextDirection.ltr,
child: Slider(
value: (state?.inSeconds ?? 0) + 0.0,
min: 0,
max: (_player?.duration?.inSeconds ?? 0) + 0.0,
onChanged: (value) {
_player.seek(Duration(seconds: value.round()));
},
),
),
return Text(
_durationTime(state) ?? "",
style: TextStyle(color: ColorConsts.textGrey1, height: 1.1, fontFamily: "Roboto"),
);
},
),
),
SizedBox(width: 8),
StreamBuilder<Duration>(
stream: _player.positionStream,
builder: (context, snapshot) {
final state = snapshot.data;
return Text(
_durationTime(state) ?? "",
style: TextStyle(color: ColorConsts.textGrey1, height: 1.1, fontFamily: "Roboto"),
);
},
),
],
)
],
)
],
),
);

@ -155,84 +155,86 @@ class _AyaRecordWidgetState extends State<AyaRecordWidget> {
height: 60,
),
),
Container(
height: 50,
margin: EdgeInsets.all(16),
padding: EdgeInsets.only(left: 12, right: 12),
decoration: BoxDecoration(
color: ColorConsts.secondaryWhite,
borderRadius: BorderRadius.circular(30),
),
child: Row(
children: [
Expanded(
child: StreamBuilder<Duration>(
if (!(recordFilePath != null && File(recordFilePath).existsSync())) SizedBox(height: 16),
if (recordFilePath != null && File(recordFilePath).existsSync())
Container(
height: 50,
margin: EdgeInsets.all(16),
padding: EdgeInsets.only(left: 12, right: 12),
decoration: BoxDecoration(
color: ColorConsts.secondaryWhite,
borderRadius: BorderRadius.circular(30),
),
child: Row(
children: [
Expanded(
child: StreamBuilder<Duration>(
stream: _audioPlayer.positionStream,
builder: (context, snapshot) {
final state = snapshot.data;
return SliderTheme(
data: SliderTheme.of(context).copyWith(
inactiveTrackColor: ColorConsts.sliderBackground,
activeTrackColor: ColorConsts.secondaryOrange,
trackHeight: 3.0,
thumbColor: ColorConsts.primaryBlack,
thumbShape: RoundSliderThumbShape(enabledThumbRadius: 6.0),
overlayColor: ColorConsts.primaryBlack.withAlpha(32),
overlayShape: RoundSliderOverlayShape(overlayRadius: 6.0),
),
child: Directionality(
textDirection: TextDirection.ltr,
child: Slider(
value: (state?.inSeconds ?? 0) + 0.0,
min: 0,
max: (_audioPlayer?.duration?.inSeconds ?? 0) + 0.0,
onChanged: (value) {},
),
),
);
},
),
),
SizedBox(width: 8),
StreamBuilder<Duration>(
stream: _audioPlayer.positionStream,
builder: (context, snapshot) {
final state = snapshot.data;
return SliderTheme(
data: SliderTheme.of(context).copyWith(
inactiveTrackColor: ColorConsts.sliderBackground,
activeTrackColor: ColorConsts.secondaryOrange,
trackHeight: 3.0,
thumbColor: ColorConsts.primaryBlack,
thumbShape: RoundSliderThumbShape(enabledThumbRadius: 6.0),
overlayColor: ColorConsts.primaryBlack.withAlpha(32),
overlayShape: RoundSliderOverlayShape(overlayRadius: 6.0),
),
child: Directionality(
textDirection: TextDirection.ltr,
child: Slider(
value: (state?.inSeconds ?? 0) + 0.0,
min: 0,
max: (_audioPlayer?.duration?.inSeconds ?? 0) + 0.0,
onChanged: (value) {},
),
),
return Text(
_durationTime(state) ?? "",
style: TextStyle(color: ColorConsts.textGrey1, height: 1.1, fontFamily: "Roboto", fontSize: 16),
);
},
),
),
SizedBox(width: 8),
StreamBuilder<Duration>(
stream: _audioPlayer.positionStream,
builder: (context, snapshot) {
final state = snapshot.data;
return Text(
_durationTime(state) ?? "",
style: TextStyle(color: ColorConsts.textGrey1, height: 1.1, fontFamily: "Roboto", fontSize: 16),
);
},
),
SizedBox(width: 8),
StreamBuilder<PlayerState>(
stream: _audioPlayer.playerStateStream,
builder: (context, snapshot) {
final state = snapshot.data?.playing ?? false;
if (state) {
if (_audioPlayer?.duration?.inSeconds == _audioPlayer?.position?.inSeconds) {
_audioPlayer.pause();
_audioPlayer.seek(Duration.zero);
SizedBox(width: 8),
StreamBuilder<PlayerState>(
stream: _audioPlayer.playerStateStream,
builder: (context, snapshot) {
final state = snapshot.data?.playing ?? false;
if (state) {
if (_audioPlayer?.duration?.inSeconds == _audioPlayer?.position?.inSeconds) {
_audioPlayer.pause();
_audioPlayer.seek(Duration.zero);
}
}
}
return IconButton(
highlightColor: Colors.transparent,
splashColor: Colors.transparent,
constraints: BoxConstraints(),
padding: EdgeInsets.only(right: 0),
icon: SvgPicture.asset(state ? "assets/icons/pause.svg" : "assets/icons/play_aya.svg", height: 16, width: 16),
onPressed: () {
state
? _audioPlayer.pause()
: _isAudioHaveError
? Utils.showToast("خطأ في تحميل ملف الصوت")
: play();
});
},
),
],
),
)
return IconButton(
highlightColor: Colors.transparent,
splashColor: Colors.transparent,
constraints: BoxConstraints(),
padding: EdgeInsets.only(right: 0),
icon: SvgPicture.asset(state ? "assets/icons/pause.svg" : "assets/icons/play_aya.svg", height: 16, width: 16),
onPressed: () {
state
? _audioPlayer.pause()
: _isAudioHaveError
? Utils.showToast("خطأ في تحميل ملف الصوت")
: play();
});
},
),
],
),
)
],
),
),

@ -0,0 +1,122 @@
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:tangheem/classes/colors.dart';
import 'package:tangheem/classes/consts.dart';
import 'package:youtube_player_flutter/youtube_player_flutter.dart';
class VideoPlayerWidget extends StatefulWidget {
final String link;
VideoPlayerWidget(this.link, {Key key}) : super(key: key);
@override
_VideoPlayerWidgetState createState() {
return _VideoPlayerWidgetState();
}
}
class _VideoPlayerWidgetState extends State<VideoPlayerWidget> {
bool doNotShowAgain = false;
YoutubePlayerController _controller;
@override
void initState() {
super.initState();
_controller = YoutubePlayerController(
initialVideoId: widget.link,
flags: YoutubePlayerFlags(
autoPlay: true,
mute: true,
),
);
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return Dialog(
insetPadding: EdgeInsets.symmetric(horizontal: 24.0, vertical: 24.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
elevation: 0,
backgroundColor: Colors.transparent,
child: Container(
width: double.infinity,
decoration: BoxDecoration(
color: ColorConsts.primaryBlue,
borderRadius: BorderRadius.circular(16),
),
padding: EdgeInsets.symmetric(vertical: MediaQuery.of(context).orientation == Orientation.portrait ? 32 : 16, horizontal: 16),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
MediaQuery.of(context).orientation == Orientation.portrait ? videoPlayer() : Expanded(child: videoPlayer()),
SizedBox(height: 8),
Row(
children: [
Expanded(
child: Text(
"لا تظهر مرة أخرى",
textAlign: TextAlign.right,
style: TextStyle(color: Colors.white),
),
),
SizedBox(width: 16),
SizedBox(
width: 12,
height: 12,
child: Checkbox(
value: doNotShowAgain,
side: BorderSide(color: Colors.white),
activeColor: ColorConsts.secondaryPink,
onChanged: (value) {
setState(() {
doNotShowAgain = value;
});
},
),
),
],
),
SizedBox(height: 16),
SizedBox(
width: double.infinity,
height: 40,
child: TextButton(
onPressed: () async {
if (doNotShowAgain) {
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setBool(GlobalConsts.doNotShowWelcomeVideo, doNotShowAgain);
}
Navigator.pop(context);
},
style: TextButton.styleFrom(
primary: Colors.white,
padding: EdgeInsets.all(2),
backgroundColor: ColorConsts.secondaryPink,
textStyle: TextStyle(fontSize: 14, fontFamily: "DroidKufi"),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(6.0),
),
),
child: Text("أغلق"),
),
),
],
),
),
);
}
Widget videoPlayer() {
return YoutubePlayer(
controller: _controller,
showVideoProgressIndicator: true,
);
}
}

@ -27,13 +27,13 @@ dependencies:
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
flutter_svg: ^0.19.3
flutter_svg: ^0.23.0+1
fluttertoast: ^7.1.8
http: ^0.13.0
image_gallery_saver: ^1.6.8
image_gallery_saver: ^1.7.1
path_provider: ^2.0.1
permission_handler: ^6.1.1
share: ^2.0.1
share: ^2.0.4
just_audio: ^0.7.2
intl: ^0.17.0
shared_preferences: ^2.0.5
@ -43,6 +43,8 @@ dependencies:
syncfusion_flutter_pdfviewer: ^19.1.59-beta
firebase_core: ^1.3.0
firebase_analytics: ^8.1.2
youtube_player_flutter: ^8.0.0
flutter_html: ^2.1.5
dev_dependencies:
flutter_test:
@ -87,6 +89,9 @@ flutter:
- asset: assets/fonts/UthmanicHafs-Regular.ttf
- asset: assets/fonts/UthmanicHafs-Bold.ttf
weight: 700
- family: BArabics
fonts:
- asset: assets/fonts/B-Arabics.ttf
#
# For details regarding fonts from package dependencies,
# see https://flutter.dev/custom-fonts/#from-packages

Loading…
Cancel
Save