voice recording added and improvements

development
Sikander Saleem 5 years ago
parent 72a18c8774
commit 3935d8ffbc

@ -8,6 +8,7 @@
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION"/>
<application <application
android:name="io.flutter.app.FlutterApplication" android:name="io.flutter.app.FlutterApplication"

@ -0,0 +1,10 @@
<svg viewBox="0 0 25.3 39.53" xmlns="http://www.w3.org/2000/svg">
<g data-name="Layer 2" id="Layer_2">
<g data-name="Layer 13" id="Layer_13">
<g>
<path style="fill: #ff8c67" d="M25.3,20.42a1.4,1.4,0,1,0-2.79,0,9.86,9.86,0,0,1-19.72,0A1.37,1.37,0,0,0,1.4,19,1.37,1.37,0,0,0,0,20.42,12.65,12.65,0,0,0,11.26,33v3.72H6.19a1.4,1.4,0,1,0,0,2.79H19.11a1.4,1.4,0,1,0,0-2.79H14.05V33A12.65,12.65,0,0,0,25.3,20.42Z"/>
<path style="fill: #ff8c67" d="M12.65,0A7.78,7.78,0,0,0,4.88,7.77v12.6a7.77,7.77,0,1,0,15.54.05V7.77A7.78,7.78,0,0,0,12.65,0Z"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 599 B

@ -1,14 +1,14 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 97.34 97.34"> <svg xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 60 60" xmlns="http://www.w3.org/2000/svg">
<g id="Layer_2" data-name="Layer 2"> <g id="Layer_2" data-name="Layer 2">
<g id="Layer_20" data-name="Layer 20"> <g data-name="Layer 13" id="Layer_13">
<g id="Group_20-2" data-name="Group 20-2"> <g data-name="Layer 2" id="Layer_2-2">
<circle cx="48.67" cy="48.67" r="48.67" style="fill: #ff8764;opacity: 0.25"/> <g data-name="Layer 1-2" id="Layer_1-2">
<circle cx="48.67" cy="48.67" r="44.31" style="fill: #ff8764;opacity: 0.5"/> <g>
<circle cx="48.67" cy="48.67" r="36.32" style="fill: #ff8764"/> <image style="opacity: 0.15000000596046448;isolation: isolate" height="60" width="60" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAACXBIWXMAAAsSAAALEgHS3X78AAAFh0lEQVRoQ+2a23LbOBBEm5K9WTvZ///R9Uq2JWEfyDYbrcGFF1cqTqZqChAJUDjoATCiPaSU8DvZodXgq9kf4K9uD60GW2wYhqHVxi198qayO3AAuQjau+89AcNezzPQwUq/7qaDCOt7gW8GFlAH9uvRhERwyepZu63gq4EDRQerq3sbNQeNPmfgW6BXAQeqOuAhqGs7NQdLAG6F6wq/CnzxpmWwESh9sDo/s2+k5E08BXW1NAzDsBR6EXABVqGO8lnrDu7AhLpOdZZaZ9ssxJdCdwMHsKriUcojxuce7bpDc5Cq6lX8MpUD7idBbRF0F3ABVpVUUHe9zz40DVtC0o9SJ/h16ncHjU5rAnfAEurR/EFKuqoM3Cv7HvhxKtmHpmGOXpWbwJNFm5Mq+gjgLynVdQKosgJrCL9hhHub/HUq+b1uN7neFdpV4OCsdWUfkMN9K7gqHQFfMIO+Tq4RocuAlqz0emg9CkfK0qnoNwB/mz/hHpr9uGklzOtUYc+IlwCkH/2AeZdvhnYReFI3ckJr+BLwCcCz1J+me6oygYFxoKrueXJOTguWriG/PqTFXF2u20fM6j4B+D75sziBuZ4VmOuX6rKdhz6Q7+jqB8zQTZVD4EKe7OvXw/kZI+wP5OBUWYE5SCpM4BPySVHVorOa11Rptg+tprCHMd13ZlWY0P8gh9aw1jWswB7KtOiMVmiuYY51U0j7+vUEg8C6fglKaKrcAvZQvsn90vl8xJyUUN0BlSPqDtgSDZY9IU1ghf6BfmDCAvFxpecyJ/wd87iocrae3UoKl2AjaB47ehzppvUdcUgDM1QJlqBn5IkMd3vdyVXlorVCmqbg0U4dncV6LFFhDtQ3LVVdYXkm6y6vz1BYWnUdt4B9bbjCuoEpeOTRsXTDPSxDWPtopnYUd+hNCkdh7Sor+CNy+JI7sMKW+jisQ3bBAm2FaQ6vk+Bru8f1eamjvX+PKgspm9YC9rVR8yi8PDJcjdYzo2e7dcMC88641KJNgdlO6Xo1Ieiwrf0BtBXWL0kV19z2ap/dVeFaO/ckpU7goslsAQMxHMur+aXiuhsrcK2Pp5EKvypyasA1dSNITfvexDVdTLjfpTXBUPdUchf4lsKRugoaATJZ0NyYz7qiDMzfwq/iCl9SvBsWaAMDOSzd81xCnpBnRJ4u6q8hPlOBT+Y6Cap6tE90gd8Bp5SS/BzuUVdfyzgsw5h9osTDgV8A/IccWhXX9e2wTWspnKRUReiqrue57KfpYg2YLwBexAnuKmtoR+s4LXrjYVYKZ/2ZRhBN+xSWr29KwGxzwgj5AuDfqXSlCe1hDXSo3LNLe0gfkK9fT//YR0P/FeUfD/qsM0ZgQtNPKCvctXZpIfC0jjmoaB1fMOfOmjKyvSunL+ccWEOeKlNpDWkqrDt2tGFVwVshrSrfMA5UVX5Dnsv6pLi6JWA9iwnnO3bPGgaA6t+Ni8AFlQl9Qa7qRzfkqhGW6nL35rHE0HeVuRGepU51FXiRukBbYWB+CDeGwUptxxDTnTd6U6ET6UedJjCafLi6umF1qQs0gEVlD21g/NKPpnLPB/8gznD29R5Bv1ud92rHUdOaCgehTWB+VlgFVlVdXX9eBH2x+lVKVzcBbXWBDmAxfZhC8x6/nAO7IH5r4cCqMpeDwrGubVbBAp3AQWgDcUgR+IgZuPRaBtZPlfZSQXVyF8ECncBAERq4B9ejy0FLO7tC3AruoIthASz/P63KXybopXdYLWD3EuRqWGAFMIDor4ssa65t3ZKUNf9ouwYWWAlM6wD36zVz6Kg+VjYMehMwrQLu11qmg9kVlLYLMM3AgX5Qt2xQe4DSdgVWC+AX2Z6Qap8GXDNOxmdB1eynAP9MW/unll/W/gB/dfsfuIIUwHATj10AAAAASUVORK5CYII="/>
<g id="Group_12-2" data-name="Group 12-2"> <g>
<g id="Group_11-2" data-name="Group 11-2"> <circle style="fill: #e4697b" cx="29.73" cy="20.73" r="11.5"/>
<path id="Path_32-2" data-name="Path 32-2" d="M63.27,48.66a1.46,1.46,0,0,0-2.92,0h0A11.68,11.68,0,1,1,37,49v-.33a1.46,1.46,0,0,0-2.92,0A14.59,14.59,0,0,0,47.22,63.2v5.91a1.46,1.46,0,1,0,2.92,0V63.19A14.59,14.59,0,0,0,63.27,48.66Z" style="fill: #fff"/> <circle style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 2.090909004211426px" cx="29.73" cy="20.73" r="11.5"/>
<path id="Path_33-2" data-name="Path 33-2" d="M48.67,56a8.79,8.79,0,0,0,8.77-8.76V35.53a8.77,8.77,0,0,0-17.53,0V47.2A8.78,8.78,0,0,0,48.67,56ZM42.83,35.53a5.84,5.84,0,1,1,11.68,0V47.2a5.84,5.84,0,1,1-11.68,0Z" style="fill: #fff"/> </g>
</g> </g>
</g> </g>
</g> </g>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

@ -0,0 +1,17 @@
<svg viewBox="0 0 97.34 97.34" xmlns="http://www.w3.org/2000/svg">
<g data-name="Layer 2" id="Layer_2">
<g data-name="Layer 13" id="Layer_13">
<g data-name="Group 20-2" id="Group_20-2">
<circle style="fill: #ff8764;opacity: 0.25" cx="48.67" cy="48.67" r="48.67"/>
<circle style="fill: #ff8764;opacity: 0.5" cx="48.67" cy="48.67" r="44.31"/>
<circle style="fill: #ff8764" cx="48.67" cy="48.67" r="36.32"/>
<g data-name="Group 12-2" id="Group_12-2">
<g data-name="Group 11-2" id="Group_11-2">
<path style="fill: #fff" d="M63.27,48.66a1.46,1.46,0,0,0-2.92,0h0A11.68,11.68,0,1,1,37,49v-.33a1.46,1.46,0,0,0-2.92,0A14.59,14.59,0,0,0,47.22,63.2v5.91a1.46,1.46,0,1,0,2.92,0V63.19A14.59,14.59,0,0,0,63.27,48.66Z" data-name="Path 32-2" id="Path_32-2"/>
<path style="fill: #fff" d="M48.67,56a8.79,8.79,0,0,0,8.77-8.76V35.53a8.77,8.77,0,0,0-17.53,0V47.2A8.78,8.78,0,0,0,48.67,56ZM42.83,35.53a5.84,5.84,0,1,1,11.68,0V47.2a5.84,5.84,0,1,1-11.68,0Z" data-name="Path 33-2" id="Path_33-2"/>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

@ -0,0 +1,30 @@
<svg xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 108.18 97.62" xmlns="http://www.w3.org/2000/svg">
<g data-name="Layer 2" id="Layer_2">
<g data-name="Layer 13" id="Layer_13">
<g>
<g data-name="Group 20-2" id="Group_20-2">
<circle style="fill: #ff8764;opacity: 0.25" cx="48.67" cy="48.95" r="48.67"/>
<circle style="fill: #ff8764;opacity: 0.5" cx="48.67" cy="48.95" r="44.31"/>
<circle style="fill: #ff8764" cx="48.67" cy="48.95" r="36.32"/>
<g data-name="Group 12-2" id="Group_12-2">
<g data-name="Group 11-2" id="Group_11-2">
<path style="fill: #fff" d="M63.27,48.94a1.46,1.46,0,0,0-2.92,0h0A11.68,11.68,0,0,1,37,49.27v-.33a1.46,1.46,0,0,0-2.92,0A14.59,14.59,0,0,0,47.22,63.48v5.91a1.46,1.46,0,1,0,2.92,0V63.47A14.59,14.59,0,0,0,63.27,48.94Z" data-name="Path 32-2" id="Path_32-2"/>
<path style="fill: #fff" d="M48.67,56.24a8.79,8.79,0,0,0,8.77-8.77V35.81a8.77,8.77,0,1,0-17.53,0V47.48A8.78,8.78,0,0,0,48.67,56.24ZM42.83,35.81a5.84,5.84,0,1,1,11.68,0V47.48a5.84,5.84,0,1,1-11.68,0Z" data-name="Path 33-2" id="Path_33-2"/>
</g>
</g>
</g>
<g data-name="Layer 2" id="Layer_2-2">
<g data-name="Layer 1-2" id="Layer_1-2">
<g>
<image style="opacity: 0.15000000596046448;isolation: isolate" height="60" transform="translate(48.18)" width="60" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAACXBIWXMAAAsSAAALEgHS3X78AAAFh0lEQVRoQ+2a23LbOBBEm5K9WTvZ///R9Uq2JWEfyDYbrcGFF1cqTqZqChAJUDjoATCiPaSU8DvZodXgq9kf4K9uD60GW2wYhqHVxi198qayO3AAuQjau+89AcNezzPQwUq/7qaDCOt7gW8GFlAH9uvRhERwyepZu63gq4EDRQerq3sbNQeNPmfgW6BXAQeqOuAhqGs7NQdLAG6F6wq/CnzxpmWwESh9sDo/s2+k5E08BXW1NAzDsBR6EXABVqGO8lnrDu7AhLpOdZZaZ9ssxJdCdwMHsKriUcojxuce7bpDc5Cq6lX8MpUD7idBbRF0F3ABVpVUUHe9zz40DVtC0o9SJ/h16ncHjU5rAnfAEurR/EFKuqoM3Cv7HvhxKtmHpmGOXpWbwJNFm5Mq+gjgLynVdQKosgJrCL9hhHub/HUq+b1uN7neFdpV4OCsdWUfkMN9K7gqHQFfMIO+Tq4RocuAlqz0emg9CkfK0qnoNwB/mz/hHpr9uGklzOtUYc+IlwCkH/2AeZdvhnYReFI3ckJr+BLwCcCz1J+me6oygYFxoKrueXJOTguWriG/PqTFXF2u20fM6j4B+D75sziBuZ4VmOuX6rKdhz6Q7+jqB8zQTZVD4EKe7OvXw/kZI+wP5OBUWYE5SCpM4BPySVHVorOa11Rptg+tprCHMd13ZlWY0P8gh9aw1jWswB7KtOiMVmiuYY51U0j7+vUEg8C6fglKaKrcAvZQvsn90vl8xJyUUN0BlSPqDtgSDZY9IU1ghf6BfmDCAvFxpecyJ/wd87iocrae3UoKl2AjaB47ehzppvUdcUgDM1QJlqBn5IkMd3vdyVXlorVCmqbg0U4dncV6LFFhDtQ3LVVdYXkm6y6vz1BYWnUdt4B9bbjCuoEpeOTRsXTDPSxDWPtopnYUd+hNCkdh7Sor+CNy+JI7sMKW+jisQ3bBAm2FaQ6vk+Bru8f1eamjvX+PKgspm9YC9rVR8yi8PDJcjdYzo2e7dcMC88641KJNgdlO6Xo1Ieiwrf0BtBXWL0kV19z2ap/dVeFaO/ckpU7goslsAQMxHMur+aXiuhsrcK2Pp5EKvypyasA1dSNITfvexDVdTLjfpTXBUPdUchf4lsKRugoaATJZ0NyYz7qiDMzfwq/iCl9SvBsWaAMDOSzd81xCnpBnRJ4u6q8hPlOBT+Y6Cap6tE90gd8Bp5SS/BzuUVdfyzgsw5h9osTDgV8A/IccWhXX9e2wTWspnKRUReiqrue57KfpYg2YLwBexAnuKmtoR+s4LXrjYVYKZ/2ZRhBN+xSWr29KwGxzwgj5AuDfqXSlCe1hDXSo3LNLe0gfkK9fT//YR0P/FeUfD/qsM0ZgQtNPKCvctXZpIfC0jjmoaB1fMOfOmjKyvSunL+ccWEOeKlNpDWkqrDt2tGFVwVshrSrfMA5UVX5Dnsv6pLi6JWA9iwnnO3bPGgaA6t+Ni8AFlQl9Qa7qRzfkqhGW6nL35rHE0HeVuRGepU51FXiRukBbYWB+CDeGwUptxxDTnTd6U6ET6UedJjCafLi6umF1qQs0gEVlD21g/NKPpnLPB/8gznD29R5Bv1ud92rHUdOaCgehTWB+VlgFVlVdXX9eBH2x+lVKVzcBbXWBDmAxfZhC8x6/nAO7IH5r4cCqMpeDwrGubVbBAp3AQWgDcUgR+IgZuPRaBtZPlfZSQXVyF8ECncBAERq4B9ejy0FLO7tC3AruoIthASz/P63KXybopXdYLWD3EuRqWGAFMIDor4ssa65t3ZKUNf9ouwYWWAlM6wD36zVz6Kg+VjYMehMwrQLu11qmg9kVlLYLMM3AgX5Qt2xQe4DSdgVWC+AX2Z6Qap8GXDNOxmdB1eynAP9MW/unll/W/gB/dfsfuIIUwHATj10AAAAASUVORK5CYII="/>
<g>
<circle style="fill: #e4697b" cx="77.91" cy="20.73" r="11.5"/>
<circle style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 2.090909004211426px" cx="77.91" cy="20.73" r="11.5"/>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

@ -12,4 +12,5 @@ class GlobalConsts {
static String email = "email"; static String email = "email";
static String password = "password"; static String password = "password";
static String bookmark = "bookmark"; static String bookmark = "bookmark";
static String fontZoomSize = "font_zoom_size";
} }

@ -59,7 +59,7 @@ class Application extends StatelessWidget {
break; break;
case TangheemDetailScreen.routeName: case TangheemDetailScreen.routeName:
className = CommonAppbar( className = CommonAppbar(
child: TangheemDetailScreen(ayatTangheemTypeMappedData: settings.arguments), child: TangheemDetailScreen(ayatTangheemTypeMappedDataList: settings.arguments),
); );
break; break;
case QuranScreen.routeName: case QuranScreen.routeName:

@ -32,7 +32,7 @@ class AyaTangheemProperty {
} }
class AyaTangheemPropertyData { class AyaTangheemPropertyData {
String ayaTangheemPropertyId; String ayaTangheemTypePropertyId;
String ayaTangheemTypeId; String ayaTangheemTypeId;
String tangheemTypePropertyId; String tangheemTypePropertyId;
String propertyValue; String propertyValue;
@ -46,7 +46,7 @@ class AyaTangheemPropertyData {
int orderNo; int orderNo;
AyaTangheemPropertyData( AyaTangheemPropertyData(
{this.ayaTangheemPropertyId, {this.ayaTangheemTypePropertyId,
this.ayaTangheemTypeId, this.ayaTangheemTypeId,
this.tangheemTypePropertyId, this.tangheemTypePropertyId,
this.propertyValue, this.propertyValue,
@ -60,7 +60,7 @@ class AyaTangheemPropertyData {
this.orderNo}); this.orderNo});
AyaTangheemPropertyData.fromJson(Map<String, dynamic> json) { AyaTangheemPropertyData.fromJson(Map<String, dynamic> json) {
ayaTangheemPropertyId = json['ayaTangheemPropertyId']; ayaTangheemTypePropertyId = json['ayaTangheemTypePropertyId'];
ayaTangheemTypeId = json['ayaTangheemTypeId']; ayaTangheemTypeId = json['ayaTangheemTypeId'];
tangheemTypePropertyId = json['tangheemTypePropertyId']; tangheemTypePropertyId = json['tangheemTypePropertyId'];
propertyValue = json['propertyValue']; propertyValue = json['propertyValue'];
@ -76,7 +76,7 @@ class AyaTangheemPropertyData {
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>(); final Map<String, dynamic> data = new Map<String, dynamic>();
data['ayaTangheemPropertyId'] = this.ayaTangheemPropertyId; data['ayaTangheemTypePropertyId'] = this.ayaTangheemTypePropertyId;
data['ayaTangheemTypeId'] = this.ayaTangheemTypeId; data['ayaTangheemTypeId'] = this.ayaTangheemTypeId;
data['tangheemTypePropertyId'] = this.tangheemTypePropertyId; data['tangheemTypePropertyId'] = this.tangheemTypePropertyId;
data['propertyValue'] = this.propertyValue; data['propertyValue'] = this.propertyValue;

@ -125,17 +125,17 @@ class TangheemProperty {
String propertyText; String propertyText;
bool isInsideTable; bool isInsideTable;
int orderNo; int orderNo;
String ayaTangheemPropertyId; String ayaTangheemTypePropertyId;
String propertyValue; String propertyValue;
TangheemProperty({this.tangheemTypePropertyId, this.propertyText, this.isInsideTable, this.orderNo, this.ayaTangheemPropertyId, this.propertyValue}); TangheemProperty({this.tangheemTypePropertyId, this.propertyText, this.isInsideTable, this.orderNo, this.ayaTangheemTypePropertyId, this.propertyValue});
TangheemProperty.fromJson(Map<String, dynamic> json) { TangheemProperty.fromJson(Map<String, dynamic> json) {
tangheemTypePropertyId = json['tangheemTypePropertyId']; tangheemTypePropertyId = json['tangheemTypePropertyId'];
propertyText = json['propertyText']; propertyText = json['propertyText'];
isInsideTable = json['isInsideTable']; isInsideTable = json['isInsideTable'];
orderNo = json['orderNo']; orderNo = json['orderNo'];
ayaTangheemPropertyId = json['ayaTangheemPropertyId']; ayaTangheemTypePropertyId = json['ayaTangheemTypePropertyId'];
propertyValue = json['propertyValue']; propertyValue = json['propertyValue'];
} }
@ -145,7 +145,7 @@ class TangheemProperty {
data['propertyText'] = this.propertyText; data['propertyText'] = this.propertyText;
data['isInsideTable'] = this.isInsideTable; data['isInsideTable'] = this.isInsideTable;
data['orderNo'] = this.orderNo; data['orderNo'] = this.orderNo;
data['ayaTangheemPropertyId'] = this.ayaTangheemPropertyId; data['ayaTangheemTypePropertyId'] = this.ayaTangheemTypePropertyId;
data['propertyValue'] = this.propertyValue; data['propertyValue'] = this.propertyValue;
return data; return data;
} }

@ -1,8 +1,10 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.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/api/tangheem_user_api_client.dart';
import 'package:tangheem/app_state/app_state.dart'; import 'package:tangheem/app_state/app_state.dart';
import 'package:tangheem/classes/colors.dart'; import 'package:tangheem/classes/colors.dart';
import 'package:tangheem/classes/consts.dart';
import 'package:tangheem/classes/utils.dart'; import 'package:tangheem/classes/utils.dart';
import 'package:tangheem/models/quick_links_model.dart'; import 'package:tangheem/models/quick_links_model.dart';
import 'package:tangheem/ui/screens/bookmark_screen.dart'; import 'package:tangheem/ui/screens/bookmark_screen.dart';
@ -31,9 +33,10 @@ class _CommonAppbarState extends State<CommonAppbar> {
void initState() { void initState() {
super.initState(); super.initState();
getQuickLinks(); getQuickLinks();
getPrefs();
} }
getQuickLinks() async { void getQuickLinks() async {
if (widget.showDrawer) { if (widget.showDrawer) {
try { try {
quickLinks = (await TangheemUserApiClient().quickLinks())?.data ?? []; quickLinks = (await TangheemUserApiClient().quickLinks())?.data ?? [];
@ -43,6 +46,13 @@ class _CommonAppbarState extends State<CommonAppbar> {
} }
} }
int fontSize;
SharedPreferences prefs;
void getPrefs() async {
prefs = await SharedPreferences.getInstance();
fontSize = prefs.getInt(GlobalConsts.fontZoomSize) ?? 18;
}
@override @override
void dispose() { void dispose() {
super.dispose(); super.dispose();
@ -122,17 +132,31 @@ class _CommonAppbarState extends State<CommonAppbar> {
), ),
Container( Container(
margin: EdgeInsets.only(top: 8, bottom: 16), margin: EdgeInsets.only(top: 8, bottom: 16),
padding: EdgeInsets.only(left: 12, right: 12), padding: EdgeInsets.only(left: 16, right: 16),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [ 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); Navigator.pushNamed(context, BookmarkScreen.routeName);
}), }),
commonIconButton("assets/icons/increase_size.svg", () {}), commonIconButton("assets/icons/increase_size.svg", () {
commonIconButton("assets/icons/reduce_size.svg", () {}), if (fontSize >= 36) {
commonIconButton("assets/icons/notification.svg", () {}), Utils.showToast("وصل حجم الخط إلى الحد الأقصى للحجم");
return;
}
fontSize += 2;
prefs.setInt(GlobalConsts.fontZoomSize, fontSize);
Utils.showToast("زيادة حجم الخط");
}),
commonIconButton("assets/icons/reduce_size.svg", () {
if (fontSize <= 12) {
Utils.showToast("وصل حجم الخط إلى الحد الأدنى للحجم");
return;
}
fontSize -= 2;
prefs.setInt(GlobalConsts.fontZoomSize, fontSize);
Utils.showToast("تم تقليل حجم الخط");
}),
commonIconButton("assets/icons/user_logged.svg", () { commonIconButton("assets/icons/user_logged.svg", () {
if (AppState().isUserLogin) { if (AppState().isUserLogin) {
Utils.showToast("أنت بالفعل تسجيل الدخول"); Utils.showToast("أنت بالفعل تسجيل الدخول");

@ -15,7 +15,7 @@ class NoDataUI extends StatelessWidget {
SvgPicture.asset("assets/icons/no_data.svg", width: 75, height: 75), SvgPicture.asset("assets/icons/no_data.svg", width: 75, height: 75),
SizedBox(height: 8), SizedBox(height: 8),
Text( Text(
"آسف! لا تتوافر بيانات", "لا توجد بيانات",
style: TextStyle(fontSize: 16, color: ColorConsts.primaryBlue.withOpacity(0.7), fontWeight: FontWeight.w600), style: TextStyle(fontSize: 16, color: ColorConsts.primaryBlue.withOpacity(0.7), fontWeight: FontWeight.w600),
), ),
SizedBox(height: 16), SizedBox(height: 16),

@ -95,7 +95,7 @@ class _HomeScreenState extends State<HomeScreen> {
Row( Row(
children: [ children: [
Expanded( Expanded(
child: CommonDropDownButton(_selectedTangheemType, hintText: "الأسلوب اللغوي", list: _tangheemList, onSelect: (index) { child: CommonDropDownButton(_selectedTangheemType, hintText: "اختر الأسلوب اللغوي", list: _tangheemList, onSelect: (index) {
if (_selectedTangheemType != index) { if (_selectedTangheemType != index) {
setState(() { setState(() {
_selectedTangheemType = index; _selectedTangheemType = index;
@ -105,7 +105,7 @@ class _HomeScreenState extends State<HomeScreen> {
), ),
SizedBox(width: 8), SizedBox(width: 8),
Expanded( Expanded(
child: CommonDropDownButton(_selectedSurah, hintText: "السورة", list: _surahList, onSelect: (index) { child: CommonDropDownButton(_selectedSurah, hintText: "اختر السورة", list: _surahList, onSelect: (index) {
if (_selectedSurah != index) { if (_selectedSurah != index) {
setState(() { setState(() {
_selectedSurah = index; _selectedSurah = index;
@ -121,11 +121,11 @@ class _HomeScreenState extends State<HomeScreen> {
highlightColor: Colors.transparent, highlightColor: Colors.transparent,
onTap: () async { onTap: () async {
if (_selectedTangheemType < 0) { if (_selectedTangheemType < 0) {
Utils.showToast("الرجاء اختيار نوع تنغيم"); Utils.showToast("الرجائ تعبئة جميع القوائم");
return; return;
} }
if (_selectedSurah < 0) { if (_selectedSurah < 0) {
Utils.showToast("الرجاء اختيار السورة"); Utils.showToast("الرجائ تعبئة جميع القوائم");
return; return;
} }
_searchFocusNode.unfocus(); _searchFocusNode.unfocus();
@ -147,7 +147,7 @@ class _HomeScreenState extends State<HomeScreen> {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Text( Text(
"ابدأ البحث", "بحث",
maxLines: 1, maxLines: 1,
style: TextStyle(fontSize: 12, color: Colors.white), style: TextStyle(fontSize: 12, color: Colors.white),
), ),
@ -171,7 +171,7 @@ class _HomeScreenState extends State<HomeScreen> {
fillColor: Colors.white, fillColor: Colors.white,
filled: true, filled: true,
hintStyle: TextStyle(color: ColorConsts.textHintGrey, fontSize: 12), hintStyle: TextStyle(color: ColorConsts.textHintGrey, fontSize: 12),
hintText: "البحث عن سورة أو آية", hintText: "البحث عن آية",
prefixIconConstraints: BoxConstraints(maxHeight: 16), prefixIconConstraints: BoxConstraints(maxHeight: 16),
prefixIcon: Padding( prefixIcon: Padding(
padding: EdgeInsets.only(right: 6), padding: EdgeInsets.only(right: 6),
@ -181,7 +181,7 @@ class _HomeScreenState extends State<HomeScreen> {
onTap: () async { onTap: () async {
_searchFocusNode.unfocus(); _searchFocusNode.unfocus();
if (_searchController.text.length < 1) { if (_searchController.text.length < 1) {
Utils.showToast("يجب إدخال بعض الكلمات للبحث"); Utils.showToast("الرجاء ادخال محتوى للبحث");
return; return;
} }
_searchFocusNode.canRequestFocus = false; _searchFocusNode.canRequestFocus = false;

@ -3,9 +3,11 @@ import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter_svg/flutter_svg.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/api/tangheem_user_api_client.dart';
import 'package:tangheem/app_state/app_state.dart'; import 'package:tangheem/app_state/app_state.dart';
import 'package:tangheem/classes/colors.dart'; import 'package:tangheem/classes/colors.dart';
import 'package:tangheem/classes/consts.dart';
import 'package:tangheem/classes/utils.dart'; import 'package:tangheem/classes/utils.dart';
import 'package:tangheem/models/aya_model.dart'; import 'package:tangheem/models/aya_model.dart';
import 'package:tangheem/models/aya_tangheem_type_mapped.dart'; import 'package:tangheem/models/aya_tangheem_type_mapped.dart';
@ -56,9 +58,19 @@ class _QuranScreenState extends State<QuranScreen> {
super.initState(); super.initState();
scrollToId = ScrollToId(scrollController: scrollController); scrollToId = ScrollToId(scrollController: scrollController);
getBookMark(); getBookMark();
getPrefs();
getSurah(); getSurah();
} }
double fontSize = 18;
SharedPreferences prefs;
void getPrefs() async {
prefs = await SharedPreferences.getInstance();
fontSize = (prefs.getInt(GlobalConsts.fontZoomSize) ?? 18) + 0.0;
setState(() {});
}
void getSurah() async { void getSurah() async {
try { try {
if (AppState().getSurahModel == null) { if (AppState().getSurahModel == null) {
@ -92,11 +104,13 @@ class _QuranScreenState extends State<QuranScreen> {
} }
int numberOfAyah = 0; int numberOfAyah = 0;
var filteredAyahList = [];
void filterData() { void filterData() {
numberOfAyah = _surahModel?.data[_selectedSurah]?.numberOfAyahs ?? 0; numberOfAyah = _surahModel?.data[_selectedSurah]?.numberOfAyahs ?? 0;
var filteredAyahList = List.generate(getNextMultiple(numberOfAyah), (index) => index + 1).toList().where((element) => element == 1 || (element % 5) == 0).toList() ?? []; 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() ?? []; _fromAyaList = filteredAyahList.getRange(0, filteredAyahList.length - 1)?.toList() ?? [];
_toAyaList = filteredAyahList.getRange(1, filteredAyahList.length)?.toList() ?? [];
// _toAyaList = filteredAyahList.getRange(1, filteredAyahList.length)?.toList() ?? [];
// _currentPage = 0; // _currentPage = 0;
// _selectedFromAya = 0; // _selectedFromAya = 0;
// _selectedToAya = 0; // _selectedToAya = 0;
@ -222,11 +236,12 @@ class _QuranScreenState extends State<QuranScreen> {
Row( Row(
children: [ children: [
Expanded( Expanded(
child: CommonDropDownButton(_selectedSurah, hintText: "السورة", list: _surahList, onSelect: (index) { child: CommonDropDownButton(_selectedSurah, hintText: "اختر السورة", list: _surahList, onSelect: (index) {
if (_selectedSurah != index) { if (_selectedSurah != index) {
_selectedSurah = index; _selectedSurah = index;
_selectedToAya = -1; _selectedToAya = -1;
_selectedFromAya = -1; _selectedFromAya = -1;
_toAyaList = [];
filterData(); filterData();
} }
}), }),
@ -236,6 +251,9 @@ class _QuranScreenState extends State<QuranScreen> {
child: CommonDropDownButton(_selectedFromAya, hintText: "من الاية", list: _fromAyaList.map((e) => "من الاية" + " $e").toList(), onSelect: (index) { child: CommonDropDownButton(_selectedFromAya, hintText: "من الاية", list: _fromAyaList.map((e) => "من الاية" + " $e").toList(), onSelect: (index) {
if (_selectedFromAya != index) { if (_selectedFromAya != index) {
_selectedFromAya = index; _selectedFromAya = index;
var abc = filteredAyahList.indexOf(_selectedFromAya);
print("index:$abc");
_toAyaList = filteredAyahList.getRange(_selectedFromAya + 1, filteredAyahList.length)?.toList() ?? [];
setState(() {}); setState(() {});
} }
}), }),
@ -254,9 +272,9 @@ class _QuranScreenState extends State<QuranScreen> {
SizedBox(height: 8), SizedBox(height: 8),
Row( Row(
children: [ children: [
commonIconButton("ابدأ البحث", "assets/icons/go_forward.svg", () { commonIconButton("عرض", "assets/icons/go_forward.svg", () {
if (_selectedSurah < 0) { if (_selectedSurah < 0) {
Utils.showToast("الرجاء اختيار السورة"); Utils.showToast("يرجى اختيار السورة");
return; return;
} else { } else {
if (_selectedFromAya < 0 && _selectedToAya < 0) { if (_selectedFromAya < 0 && _selectedToAya < 0) {
@ -270,15 +288,15 @@ class _QuranScreenState extends State<QuranScreen> {
} }
} }
}), }),
SizedBox(width: 8), // SizedBox(width: 8),
commonIconButton( // commonIconButton(
"مسح البحث", // "مسح البحث",
"assets/icons/cancel.svg", // "assets/icons/cancel.svg",
(_selectedSurah == -1 || _selectedFromAya == -1 || _selectedToAya == -1) // (_selectedSurah == -1 || _selectedFromAya == -1 || _selectedToAya == -1)
? null // ? null
: () { // : () {
_clearFilterAndRefreshData(); // _clearFilterAndRefreshData();
}), // }),
], ],
), ),
SizedBox(height: 16), SizedBox(height: 16),
@ -372,21 +390,6 @@ class _QuranScreenState extends State<QuranScreen> {
), ),
), ),
), ),
// SizedBox(height: 8),
// AyaScrollViewer(
// scrollDirection: Axis.horizontal,
// scrollToId: scrollToId,
// children: <ScrollContent>[
// 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), SizedBox(height: 4),
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
@ -471,7 +474,7 @@ class _QuranScreenState extends State<QuranScreen> {
); );
} }
void _selectTangheemType(List<AyatTangheemTypeMappedData> list) async { void _selectTangheemType(List<String> list, List<AyatTangheemTypeMappedData> dataList) async {
SimpleDialog dialog = SimpleDialog( SimpleDialog dialog = SimpleDialog(
title: Text( title: Text(
'اختر نوع تنغيم', 'اختر نوع تنغيم',
@ -481,19 +484,20 @@ class _QuranScreenState extends State<QuranScreen> {
children: list children: list
.map((e) => SimpleDialogOption( .map((e) => SimpleDialogOption(
child: Text( child: Text(
e.tangheemTypeName, e,
textDirection: TextDirection.rtl, textDirection: TextDirection.rtl,
style: TextStyle(color: ColorConsts.primaryBlue), style: TextStyle(color: ColorConsts.primaryBlue),
), ),
onPressed: () { onPressed: () {
Navigator.pop(context); Navigator.pop(context);
Navigator.pushNamed(context, TangheemDetailScreen.routeName, arguments: e); var list = _ayatTangheemTypeMapped?.data?.where((element) => element.tangheemTypeName == e)?.toList() ?? [];
Navigator.pushNamed(context, TangheemDetailScreen.routeName, arguments: list);
}, },
)) ))
.toList(), .toList(),
); );
showDialog( await showDialog(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return dialog; return dialog;
@ -536,7 +540,7 @@ class _QuranScreenState extends State<QuranScreen> {
style: TextStyle( style: TextStyle(
backgroundColor: _selectedAyaForBookmark?.ayahID == element.ayahID ? ColorConsts.secondaryOrange.withOpacity(.4) : Colors.transparent, backgroundColor: _selectedAyaForBookmark?.ayahID == element.ayahID ? ColorConsts.secondaryOrange.withOpacity(.4) : Colors.transparent,
fontFamily: "UthmanicHafs", fontFamily: "UthmanicHafs",
fontSize: 18, fontSize: fontSize,
color: ColorConsts.primaryBlue, color: ColorConsts.primaryBlue,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@ -545,7 +549,7 @@ class _QuranScreenState extends State<QuranScreen> {
setState(() { setState(() {
if (_selectedAyaForBookmark == null) { if (_selectedAyaForBookmark == null) {
_selectedAyaForBookmark = BookMarkModel.fromJson(element.toJson()); _selectedAyaForBookmark = BookMarkModel.fromJson(element.toJson());
addBookMarkOption(); showAyaOptions();
return; return;
} }
_selectedAyaForBookmark = null; _selectedAyaForBookmark = null;
@ -561,7 +565,7 @@ class _QuranScreenState extends State<QuranScreen> {
text: "\n" + "$_currentPage", text: "\n" + "$_currentPage",
style: TextStyle( style: TextStyle(
fontFamily: "UthmanicHafs", fontFamily: "UthmanicHafs",
fontSize: 18, fontSize: fontSize,
color: ColorConsts.primaryBlue, color: ColorConsts.primaryBlue,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@ -579,8 +583,7 @@ class _QuranScreenState extends State<QuranScreen> {
); );
} }
void addBookMarkOption() { void showAyaOptions() {
var isAyaHaveTagheem = _ayatTangheemTypeMapped?.data?.firstWhere((element) => element.ayahNo == _selectedAyaForBookmark.ayahID, orElse: () => null);
showModalBottomSheet( showModalBottomSheet(
context: context, context: context,
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
@ -600,36 +603,45 @@ class _QuranScreenState extends State<QuranScreen> {
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
if (isAyaHaveTagheem != null) InkWell(
InkWell( onTap: () async {
onTap: () { Navigator.pop(context);
Navigator.pop(context); List<AyatTangheemTypeMappedData> list = [];
List<AyatTangheemTypeMappedData> _ayatList = _ayatTangheemTypeMapped.data?.where((element) => element.ayahNo == _selectedAyaForBookmark.ayahID)?.toList() ?? [];
if (_ayatList.length > 1) { list = _ayatTangheemTypeMapped?.data?.where((element) => element.ayahNo == _selectedAyaForBookmark.ayahID)?.toList() ?? [];
_selectTangheemType(_ayatList); if (list.isEmpty) {
} else { Utils.showToast("لا توجد أساليب تنغيم في هذه الأية");
Navigator.pushNamed(context, TangheemDetailScreen.routeName, arguments: _ayatList.first); return;
} }
},
child: Row( List<String> tempList = list.map((element) => element.tangheemTypeName).toList().toSet().toList();
children: [Text("عرض تنغيم")],
), if (tempList.length > 1) {
_selectTangheemType(tempList, list);
return;
}
Navigator.pushNamed(context, TangheemDetailScreen.routeName, arguments: list);
},
child: Row(
children: [Text("تفاصيل التنغيم")],
), ),
if (isAyaHaveTagheem != null) SizedBox(height: 8), ),
SizedBox(height: 8),
InkWell( InkWell(
onTap: () { onTap: () {
Navigator.pop(context); Navigator.pop(context);
var temp = _bookMark.firstWhere((element) => element.ayahID == _selectedAyaForBookmark.ayahID, orElse: () => null); var temp = _bookMark.firstWhere((element) => element.ayahID == _selectedAyaForBookmark.ayahID, orElse: () => null);
if (temp != null) { if (temp != null) {
Utils.showToast("تمت إضافة إشارة مرجعية بالفعل"); //
Utils.showToast("هذه الأية مضافة سابقا");
return; return;
} }
_bookMark.add(_selectedAyaForBookmark); _bookMark.add(_selectedAyaForBookmark);
BookMarkModel.saveToPrefs(_bookMark); BookMarkModel.saveToPrefs(_bookMark);
Utils.showToast("وأضاف المرجعية"); Utils.showToast("تم اضافة الأية كمرجع");
}, },
child: Row( child: Row(
children: [Text("أضف إلى المرجعية")], children: [Text("اضافة الأية كمرجع؟")],
), ),
), ),
], ],

@ -1,23 +1,27 @@
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:tangheem/api/admin_configuration_api_client.dart'; import 'package:tangheem/api/admin_configuration_api_client.dart';
import 'package:tangheem/api/tangheem_user_api_client.dart'; import 'package:tangheem/api/tangheem_user_api_client.dart';
import 'package:tangheem/app_state/app_state.dart'; import 'package:tangheem/app_state/app_state.dart';
import 'package:tangheem/classes/colors.dart'; import 'package:tangheem/classes/colors.dart';
import 'package:tangheem/classes/consts.dart';
import 'package:tangheem/classes/utils.dart'; import 'package:tangheem/classes/utils.dart';
import 'package:tangheem/models/aya_tangheem_type_mapped.dart'; import 'package:tangheem/models/aya_tangheem_type_mapped.dart';
import 'package:tangheem/models/discussion_model.dart'; import 'package:tangheem/models/discussion_model.dart';
import 'package:tangheem/ui/dialogs/discussion_input_dialog.dart'; import 'package:tangheem/ui/dialogs/discussion_input_dialog.dart';
import 'package:tangheem/widgets/aya_player_widget.dart'; import 'package:tangheem/widgets/aya_player_widget.dart';
import 'package:tangheem/widgets/aya_record_widget.dart';
import 'package:tangheem/widgets/text_highlight_widget.dart'; import 'package:tangheem/widgets/text_highlight_widget.dart';
import 'package:tangheem/extensions/string_extensions.dart'; import 'package:tangheem/extensions/string_extensions.dart';
import 'login_screen.dart'; import 'login_screen.dart';
class TangheemDetailScreen extends StatefulWidget { class TangheemDetailScreen extends StatefulWidget {
static const String routeName = "/tangheem_detail"; static const String routeName = "/tangheem_detail";
final AyatTangheemTypeMappedData ayatTangheemTypeMappedData; final List<AyatTangheemTypeMappedData> ayatTangheemTypeMappedDataList;
TangheemDetailScreen({Key key, this.ayatTangheemTypeMappedData}) : super(key: key); // final AyatTangheemTypeMappedData ayatTangheemTypeMappedData;
TangheemDetailScreen({Key key, this.ayatTangheemTypeMappedDataList}) : super(key: key);
@override @override
_TangheemDetailScreenState createState() { _TangheemDetailScreenState createState() {
@ -27,29 +31,54 @@ class TangheemDetailScreen extends StatefulWidget {
class _TangheemDetailScreenState extends State<TangheemDetailScreen> { class _TangheemDetailScreenState extends State<TangheemDetailScreen> {
GlobalKey _globalKey = GlobalKey(); GlobalKey _globalKey = GlobalKey();
List<TangheemProperty> _tangheemInsideTableTrueList = [];
List<TangheemProperty> _tangheemInsideTableValueList = []; List<VoiceNote> voiceNoteList = [];
List<TangheemProperty> _tangheemInsideTableEmptyList = [];
List<String> _tangheemWords = []; List<AyatTangheemTypeMappedData> ayatTangheemTypeMappedDataList = [];
int _discussionPage = -1; int _discussionPage = -1;
AyatTangheemTypeMapped _ayatTangheemTypeMapped; AyatTangheemTypeMappedData _ayatTangheemTypeMappedFirstData;
AyatTangheemTypeMappedData _ayatTangheemTypeMappedData;
DiscussionModel _discussionModel; DiscussionModel _discussionModel;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_tangheemInsideTableValueList = [];
_tangheemInsideTableEmptyList = []; ayatTangheemTypeMappedDataList = widget.ayatTangheemTypeMappedDataList;
filterData(); _ayatTangheemTypeMappedFirstData = ayatTangheemTypeMappedDataList.first;
filterVoiceListData();
getPrefs();
getTangheemDiscussion(); getTangheemDiscussion();
} }
double fontSize = 18;
SharedPreferences prefs;
void getPrefs() async {
prefs = await SharedPreferences.getInstance();
fontSize = (prefs.getInt(GlobalConsts.fontZoomSize) ?? 18) + 0.0;
setState(() {});
}
String getArabicIndexWord(int index) {
if (index == 0) {
return 'الأولى';
} else if (index == 1) {
return 'الثانية';
} else if (index == 2) {
return 'الثالثة';
} else if (index == 3) {
return 'الرابعة';
} else if (index == 4) {
return 'الخامسة';
}
return "";
}
void getTangheemDiscussion() async { void getTangheemDiscussion() async {
Utils.showLoading(context); Utils.showLoading(context);
try { try {
_discussionModel = await TangheemUserApiClient().getDiscussionByTangheemID(_discussionPage, widget.ayatTangheemTypeMappedData.ayaTangheemTypeId); _discussionModel = await TangheemUserApiClient().getDiscussionByTangheemID(_discussionPage, _ayatTangheemTypeMappedFirstData.ayaTangheemTypeId);
Utils.hideLoading(context); Utils.hideLoading(context);
setState(() {}); setState(() {});
} catch (ex, tr) { } catch (ex, tr) {
@ -61,7 +90,7 @@ class _TangheemDetailScreenState extends State<TangheemDetailScreen> {
void sendComment(String discussionText) async { void sendComment(String discussionText) async {
Utils.showLoading(context); Utils.showLoading(context);
try { try {
await AdminConfigurationApiClient().addDiscussion(discussionText, widget.ayatTangheemTypeMappedData.ayaTangheemTypeId); await AdminConfigurationApiClient().addDiscussion(discussionText, _ayatTangheemTypeMappedFirstData.ayaTangheemTypeId);
Utils.showToast("تم إرسال التعليق ، سيكون مرئيًا بمجرد موافقة المسؤول عليه"); Utils.showToast("تم إرسال التعليق ، سيكون مرئيًا بمجرد موافقة المسؤول عليه");
Utils.hideLoading(context); Utils.hideLoading(context);
Navigator.pop(context); Navigator.pop(context);
@ -72,12 +101,10 @@ class _TangheemDetailScreenState extends State<TangheemDetailScreen> {
} }
} }
void filterData() { void filterVoiceListData() {
_ayatTangheemTypeMappedData = widget.ayatTangheemTypeMappedData; ayatTangheemTypeMappedDataList.forEach((element) {
_tangheemWords.add(_ayatTangheemTypeMappedData.highlightText ?? ""); voiceNoteList.addAll(element.voiceNote);
_tangheemInsideTableTrueList = _ayatTangheemTypeMappedData?.property?.where((element) => (element.isInsideTable) && (element.propertyValue ?? "").isNotEmpty)?.toList() ?? []; });
_tangheemInsideTableValueList = _ayatTangheemTypeMappedData?.property?.where((element) => (!element.isInsideTable) && (element.propertyValue ?? "").isNotEmpty)?.toList() ?? [];
// _tangheemInsideTableEmptyList = _ayatTangheemTypeMappedData?.property?.where((element) => (!element.isInsideTable) && (element.propertyValue ?? "").isEmpty)?.toList() ?? [];
} }
@override @override
@ -90,13 +117,13 @@ class _TangheemDetailScreenState extends State<TangheemDetailScreen> {
return Container( return Container(
padding: EdgeInsets.fromLTRB(16, 24, 16, 0), padding: EdgeInsets.fromLTRB(16, 24, 16, 0),
width: double.infinity, width: double.infinity,
child: _ayatTangheemTypeMappedData == null child: _ayatTangheemTypeMappedFirstData == null
? SizedBox() ? SizedBox()
: Column( : Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
_ayatTangheemTypeMappedData.tangheemTypeName ?? "", _ayatTangheemTypeMappedFirstData.tangheemTypeName ?? "",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20, color: ColorConsts.primaryBlue, height: 1.5), style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20, color: ColorConsts.primaryBlue, height: 1.5),
), ),
SizedBox(height: 8), SizedBox(height: 8),
@ -122,94 +149,127 @@ class _TangheemDetailScreenState extends State<TangheemDetailScreen> {
child: RepaintBoundary( child: RepaintBoundary(
key: _globalKey, key: _globalKey,
child: Material( child: Material(
color: Colors.white, color: Colors.white,
child: ListView( child: ListView.builder(
physics: NeverScrollableScrollPhysics(), physics: NeverScrollableScrollPhysics(),
shrinkWrap: true, shrinkWrap: true,
padding: EdgeInsets.all(4), itemCount: ayatTangheemTypeMappedDataList.length > 5 ? 5 : ayatTangheemTypeMappedDataList.length,
children: [ itemBuilder: (context, index) {
TextHighLightWidget( var _ayatTangheemTypeMappedData = ayatTangheemTypeMappedDataList[index];
text: _ayatTangheemTypeMappedData.reverseAyatNumber() ?? "", List<TangheemProperty> _tangheemInsideTableTrueList = [];
valueColor: ColorConsts.primaryBlue, List<TangheemProperty> _tangheemInsideTableValueList = [];
highlights: _tangheemWords, List<TangheemProperty> _tangheemInsideTableEmptyList = [];
style: TextStyle( List<String> _tangheemWords = [];
fontFamily: "UthmanicHafs",
fontSize: 18, _tangheemWords.add(_ayatTangheemTypeMappedData.highlightText ?? "");
fontWeight: FontWeight.bold, _tangheemInsideTableTrueList =
), _ayatTangheemTypeMappedData?.property?.where((element) => (element.isInsideTable) && (element.propertyValue ?? "").isNotEmpty)?.toList() ?? [];
), _tangheemInsideTableValueList =
SizedBox(height: 16), _ayatTangheemTypeMappedData?.property?.where((element) => (!element.isInsideTable) && (element.propertyValue ?? "").isNotEmpty)?.toList() ?? [];
ListView.separated( // _tangheemInsideTableEmptyList = _ayatTangheemTypeMappedData?.property?.where((element) => (!element.isInsideTable) && (element.propertyValue ?? "").isEmpty)?.toList() ?? [];
itemCount: _tangheemInsideTableValueList.length,
physics: NeverScrollableScrollPhysics(), return ListView(
shrinkWrap: true, physics: NeverScrollableScrollPhysics(),
separatorBuilder: (context, index) { shrinkWrap: true,
return Divider( padding: EdgeInsets.all(4),
color: Colors.white, children: [
height: 1, Row(
thickness: 0, children: [
); Text(
}, " جمله ${_ayatTangheemTypeMappedData.tangheemTypeName} ${getArabicIndexWord(index)} ",
itemBuilder: (context, index) { style: TextStyle(fontWeight: FontWeight.bold, color: Colors.white, backgroundColor: ColorConsts.primaryBlue),
return Row(
children: [
Expanded(
child: Container(
height: 40,
padding: EdgeInsets.only(left: 4, right: 8),
alignment: Alignment.centerRight,
child: Text(
_tangheemInsideTableValueList[index].propertyText,
style: TextStyle(fontWeight: FontWeight.bold, color: ColorConsts.secondaryOrange),
),
color: ColorConsts.secondaryWhite,
), ),
), Expanded(
SizedBox(width: 8), child: Container(height: 2, color: ColorConsts.primaryBlue),
Expanded(
child: Container(
height: 40,
padding: EdgeInsets.only(left: 4, right: 8),
alignment: Alignment.centerRight,
child: Text(
_tangheemInsideTableValueList[index].propertyValue,
style: TextStyle(color: ColorConsts.primaryBlack),
),
color: ColorConsts.secondaryWhite,
), ),
) ],
],
);
}),
if (_tangheemInsideTableTrueList.isNotEmpty)
Container(
color: ColorConsts.primaryBlue,
margin: EdgeInsets.only(top: 8, bottom: 8),
padding: EdgeInsets.all(8),
child: Column(
children: [
Text(
_ayatTangheemTypeMappedData.tangheemTypeName ?? "",
style: TextStyle(fontWeight: FontWeight.bold, color: Colors.white),
), ),
SizedBox(height: 8), SizedBox(height: 8),
tangheemPropertyView(_tangheemInsideTableTrueList) TextHighLightWidget(
text: _ayatTangheemTypeMappedData.reverseAyatNumber() ?? "",
valueColor: ColorConsts.primaryBlue,
highlights: _tangheemWords,
highLightFontSize: fontSize,
style: TextStyle(
fontFamily: "UthmanicHafs",
fontSize: fontSize,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 16),
ListView.separated(
itemCount: _tangheemInsideTableValueList.length,
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
separatorBuilder: (context, index) {
return Divider(
color: Colors.white,
height: 1,
thickness: 0,
);
},
itemBuilder: (context, index) {
return Row(
children: [
Expanded(
child: Container(
height: 40,
padding: EdgeInsets.only(left: 4, right: 8),
alignment: Alignment.centerRight,
child: Text(
_tangheemInsideTableValueList[index].propertyText,
style: TextStyle(fontWeight: FontWeight.bold, color: ColorConsts.secondaryOrange),
),
color: ColorConsts.secondaryWhite,
),
),
SizedBox(width: 8),
Expanded(
child: Container(
height: 40,
padding: EdgeInsets.only(left: 4, right: 8),
alignment: Alignment.centerRight,
child: Text(
_tangheemInsideTableValueList[index].propertyValue,
style: TextStyle(color: ColorConsts.primaryBlack),
),
color: ColorConsts.secondaryWhite,
),
)
],
);
}),
if (_tangheemInsideTableTrueList.isNotEmpty)
Container(
color: ColorConsts.primaryBlue,
margin: EdgeInsets.only(top: 8, bottom: 8),
padding: EdgeInsets.all(8),
child: Column(
children: [
Text(
_ayatTangheemTypeMappedData.tangheemTypeName ?? "",
style: TextStyle(fontWeight: FontWeight.bold, color: Colors.white),
),
SizedBox(height: 8),
tangheemPropertyView(_tangheemInsideTableTrueList)
],
),
),
tangheemPropertyView(_tangheemInsideTableEmptyList)
], ],
), );
), })),
tangheemPropertyView(_tangheemInsideTableEmptyList)
],
),
),
), ),
), ),
), ),
SizedBox(height: 8), SizedBox(height: 8),
discussionView(_discussionModel?.data ?? []), discussionView(_discussionModel?.data ?? []),
SizedBox(height: 16),
AyaRecordWidget()
], ],
), ),
), ),
AyaPlayerWidget(surahName: _ayatTangheemTypeMappedData.surahNameAr ?? "", globalKey: _globalKey, voiceNoteList: _ayatTangheemTypeMappedData?.voiceNote ?? []) AyaPlayerWidget(surahName: _ayatTangheemTypeMappedFirstData?.surahNameAr ?? "", globalKey: _globalKey, voiceNoteList: voiceNoteList)
], ],
), ),
); );
@ -308,60 +368,71 @@ class _TangheemDetailScreenState extends State<TangheemDetailScreen> {
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
), ),
child: ListView.separated( child: _discussionList.length > 1
padding: EdgeInsets.only(top: 4, bottom: 24), ? ListView.separated(
shrinkWrap: true, padding: EdgeInsets.only(top: 4, bottom: 24),
physics: NeverScrollableScrollPhysics(), shrinkWrap: true,
itemCount: _discussionList.length, physics: NeverScrollableScrollPhysics(),
separatorBuilder: (context, index) => SizedBox(height: 16), itemCount: _discussionList.length,
itemBuilder: (context, index) { separatorBuilder: (context, index) => SizedBox(height: 16),
return Column( itemBuilder: (context, index) {
crossAxisAlignment: CrossAxisAlignment.start, return Column(
mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start,
children: [ mainAxisSize: MainAxisSize.min,
Row( children: [
children: [ Row(
SvgPicture.asset( children: [
"assets/icons/chat_user.svg", SvgPicture.asset(
width: 60, "assets/icons/chat_user.svg",
height: 60, width: 60,
), height: 60,
SizedBox(width: 8), ),
Column( SizedBox(width: 8),
crossAxisAlignment: CrossAxisAlignment.start, Column(
mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start,
children: [ mainAxisAlignment: MainAxisAlignment.center,
Text( children: [
"تعليق على الآية ${widget.ayatTangheemTypeMappedData.ayatNumberInSurah}", Text(
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16, color: ColorConsts.primaryBlue, height: 1.5), "تعليق على الآية ${_ayatTangheemTypeMappedFirstData.ayatNumberInSurah}",
), style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16, color: ColorConsts.primaryBlue, height: 1.5),
SizedBox(height: 4), ),
Text( SizedBox(height: 4),
_discussionList[index].date.toFormattedDate(), Text(
style: TextStyle(fontSize: 12, color: ColorConsts.textGrey, height: 1), _discussionList[index].date.toFormattedDate(),
), style: TextStyle(fontSize: 12, color: ColorConsts.textGrey, height: 1),
], ),
) ],
], )
), ],
SizedBox(height: 4), ),
Column( SizedBox(height: 4),
crossAxisAlignment: CrossAxisAlignment.start, Column(
children: [ crossAxisAlignment: CrossAxisAlignment.start,
// Text( children: [
// "عنوان التعليق", Text(
// style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14, color: ColorConsts.primaryBlue, height: 1.5), "تعليق من: " + _discussionList[index].userName,
// ), style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14, color: ColorConsts.primaryBlue, height: 1.5),
Text( ),
_discussionList[index].discussionText, Text(
style: TextStyle(fontSize: 14, color: ColorConsts.textGrey, height: 1.4), _discussionList[index].discussionText,
), style: TextStyle(fontSize: 14, color: ColorConsts.textGrey, height: 1.4),
], ),
) if ((_discussionList[index]?.adminResponse ?? "").isNotEmpty) SizedBox(height: 4),
], if ((_discussionList[index]?.adminResponse ?? "").isNotEmpty)
); Text(
}, "تعليق من: " + _discussionList[index].adminResponse,
), style: TextStyle(fontSize: 14, color: ColorConsts.textGrey, height: 1.4),
),
],
)
],
);
},
)
: Text(
"لا يوجد تعليقات",
style: TextStyle(fontSize: 12, color: ColorConsts.primaryBlue, height: 1.5),
),
), ),
Positioned( Positioned(
bottom: 0, bottom: 0,
@ -369,11 +440,42 @@ class _TangheemDetailScreenState extends State<TangheemDetailScreen> {
borderRadius: BorderRadius.circular(30), borderRadius: BorderRadius.circular(30),
onTap: () async { onTap: () async {
if (!AppState().isUserLogin) { if (!AppState().isUserLogin) {
await Navigator.pushNamed(context, LoginScreen.routeName); Widget cancelButton = FlatButton(
if (!AppState().isUserLogin) { child: Text("أرغب بالتسجيل"),
Utils.showToast("يجب عليك تسجيل الدخول للتعليق"); onPressed: () async {
return; Navigator.pop(context);
} await Navigator.pushNamed(context, LoginScreen.routeName);
if (!AppState().isUserLogin) {
return;
}
},
);
Widget continueButton = FlatButton(
child: Text("استمرار كضيف"),
onPressed: () {
Navigator.pop(context);
return;
},
);
// set up the AlertDialog
AlertDialog alert = AlertDialog(
content: Text("هذه الخاصية متاحه فقط للأعضاء المسجلين"),
actions: [
cancelButton,
continueButton,
],
);
// show the dialog
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
return;
} }
showDialog( showDialog(
context: context, context: context,

@ -7,6 +7,7 @@ import 'package:tangheem/models/aya_tangheem_type_mapped.dart';
import 'package:tangheem/models/surah_model.dart'; import 'package:tangheem/models/surah_model.dart';
import 'package:tangheem/ui/misc/no_data_ui.dart'; import 'package:tangheem/ui/misc/no_data_ui.dart';
import 'package:tangheem/ui/screens/tangheem_detail_screen.dart'; import 'package:tangheem/ui/screens/tangheem_detail_screen.dart';
import 'package:tangheem/widgets/aya_record_widget.dart';
import 'package:tangheem/widgets/text_highlight_widget.dart'; import 'package:tangheem/widgets/text_highlight_widget.dart';
class TangheemScreen extends StatefulWidget { class TangheemScreen extends StatefulWidget {
@ -56,7 +57,8 @@ class _TangheemScreenState extends State<TangheemScreen> {
return _dataList == null return _dataList == null
? SizedBox() ? SizedBox()
: _dataList.isEmpty : _dataList.isEmpty
? NoDataUI() ? //AyaRecordWidget()
NoDataUI()
: ListView.separated( : ListView.separated(
physics: BouncingScrollPhysics(), physics: BouncingScrollPhysics(),
padding: EdgeInsets.all(16), padding: EdgeInsets.all(16),
@ -67,7 +69,9 @@ class _TangheemScreenState extends State<TangheemScreen> {
itemBuilder: (context, index) { itemBuilder: (context, index) {
return InkWell( return InkWell(
onTap: () { onTap: () {
Navigator.pushNamed(context, TangheemDetailScreen.routeName, arguments: _dataList[index]); List<AyatTangheemTypeMappedData> list = [];
list = _ayatTangheemTypeMapped?.data?.where((element) => (element.ayahNo == _dataList[index].ayahNo) && (element.tangheemTypeId == _dataList[index].tangheemTypeId))?.toList() ?? [];
Navigator.pushNamed(context, TangheemDetailScreen.routeName, arguments:list);
}, },
borderRadius: BorderRadius.circular(4), borderRadius: BorderRadius.circular(4),
child: Container( child: Container(
@ -89,7 +93,7 @@ class _TangheemScreenState extends State<TangheemScreen> {
style: TextStyle(fontSize: 12, color: ColorConsts.primaryBlue), style: TextStyle(fontSize: 12, color: ColorConsts.primaryBlue),
), ),
Text( Text(
" ${_dataList[index].ayahNo}", " ${_dataList[index].ayatNumberInSurah}",
style: TextStyle(fontSize: 14, color: ColorConsts.secondaryOrange), style: TextStyle(fontSize: 14, color: ColorConsts.secondaryOrange),
), ),
], ],

@ -79,6 +79,26 @@ class _AyaPlayerWidgetState extends State<AyaPlayerWidget> {
super.dispose(); super.dispose();
} }
int _tempIndex;
Uint8List temp;
// made this dedicated function to remove avatar flashing
DecorationImage getDecodedImage(int index) {
if (_tempIndex == null || _tempIndex != index) {
_tempIndex = index;
String encodedImage = widget.voiceNoteList.elementAt(index).profilePicture;
if (encodedImage.contains("data:image/png;base64,")) {
encodedImage = encodedImage.replaceAll("data:image/png;base64,", "");
}
temp = base64Decode(encodedImage);
}
return DecorationImage(
fit: BoxFit.cover,
image: MemoryImage(temp),
);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
@ -106,7 +126,9 @@ class _AyaPlayerWidgetState extends State<AyaPlayerWidget> {
), ),
itemBuilder: (context) { itemBuilder: (context) {
var _voiceList = widget.voiceNoteList; var _voiceList = widget.voiceNoteList;
return List.generate(_voiceList.length, (index) { var length = _voiceList.length < 2 ? 0 : _voiceList.length;
return List.generate(length, (index) {
return PopupMenuItem( return PopupMenuItem(
value: index, value: index,
child: Text( child: Text(
@ -120,21 +142,14 @@ class _AyaPlayerWidgetState extends State<AyaPlayerWidget> {
StreamBuilder<int>( StreamBuilder<int>(
stream: _player.currentIndexStream, stream: _player.currentIndexStream,
builder: (context, snapshot) { builder: (context, snapshot) {
final state = snapshot.data; int state = snapshot.data;
if (state == null) return SizedBox(); if (state == null) return SizedBox();
return Container( return Container(
width: 50.0, width: 50.0,
margin: EdgeInsets.only(left: 8, right: 8), margin: EdgeInsets.only(left: 8, right: 8),
height: 50.0, height: 50.0,
decoration: BoxDecoration( decoration: BoxDecoration(
image: widget.voiceNoteList.length < 1 image: widget.voiceNoteList.length < 1 ? null : getDecodedImage(state),
? null
: DecorationImage(
fit: BoxFit.cover,
image: MemoryImage(
base64Decode(widget.voiceNoteList.elementAt(state).profilePicture),
),
),
borderRadius: BorderRadius.all( borderRadius: BorderRadius.all(
Radius.circular(30.0), Radius.circular(30.0),
), ),
@ -153,7 +168,6 @@ class _AyaPlayerWidgetState extends State<AyaPlayerWidget> {
); );
}, },
), ),
Expanded( Expanded(
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
@ -182,22 +196,17 @@ class _AyaPlayerWidgetState extends State<AyaPlayerWidget> {
commonIconButton("assets/icons/download_aya.svg", () async { commonIconButton("assets/icons/download_aya.svg", () async {
if (await _requestPermission()) { if (await _requestPermission()) {
if (await _saveAya()) { if (await _saveAya()) {
Utils.showToast("آية تم الحفظ بنجاح"); Utils.showToast("تم حفظ الأية بنجاح");
} else { } else {
Utils.showToast("فشل في حفظ الآية"); Utils.showToast("خطأ في حفظ الآية");
} }
} else { } else {
Utils.showToast("يجب أن تمنح الإذن لتنزيل الآية"); Utils.showToast("يجب اعطاء الاذن لتنزيل الآية");
} }
}), }),
commonIconButton("assets/icons/share_aya.svg", () { commonIconButton("assets/icons/share_aya.svg", () {
_shareAya(); _shareAya();
}), }),
// commonIconButton("assets/icons/bookmark.svg", () {}),
// commonIconButton("assets/icons/audio_level.svg", () async {
// // var vol = await VolumeController.getVolume();
// VolumeController.maxVolume();
// }),
], ],
), ),
SizedBox(height: 8), SizedBox(height: 8),
@ -222,7 +231,7 @@ class _AyaPlayerWidgetState extends State<AyaPlayerWidget> {
state state
? _player.pause() ? _player.pause()
: _isAudioHaveError : _isAudioHaveError
? Utils.showToast("لم يتم تحميل ملف الصوت") ? Utils.showToast("خطأ في تحميل ملف الصوت")
: _player.play(); : _player.play();
}); });
}, },

@ -0,0 +1,311 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:just_audio/just_audio.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:record_mp3/record_mp3.dart';
import 'package:tangheem/classes/colors.dart';
import 'package:tangheem/classes/utils.dart';
class AyaRecordWidget extends StatefulWidget {
AyaRecordWidget({Key key}) : super(key: key);
@override
_AyaRecordWidgetState createState() => _AyaRecordWidgetState();
}
class _AyaRecordWidgetState extends State<AyaRecordWidget> {
bool _isRecording = false;
AudioPlayer _audioPlayer;
bool _isAudioHaveError = false;
@override
void initState() {
super.initState();
_audioPlayer = AudioPlayer();
}
@override
void dispose() {
_audioPlayer.dispose();
if (recordFilePath != null && File(recordFilePath).existsSync()) {
File(recordFilePath).deleteSync();
}
super.dispose();
}
Future<bool> checkPermission() async {
if (!await Permission.microphone.isGranted) {
PermissionStatus status = await Permission.microphone.request();
if (status != PermissionStatus.granted) {
return false;
}
}
return true;
}
void startRecord() async {
bool hasPermission = await checkPermission();
if (hasPermission) {
recordFilePath = await getFilePath();
_isRecording = true;
RecordMp3.instance.start(recordFilePath, (type) {
_isRecording = false;
setState(() {});
});
} else {
Utils.showToast("يجب أن تمنح الإذن للتسجيل");
}
setState(() {});
}
void stopRecord() async {
bool _isStop = RecordMp3.instance.stop();
if (_isStop) {
_isRecording = false;
setState(() {});
}
}
String recordFilePath;
void play() async {
if (recordFilePath != null && File(recordFilePath).existsSync()) {
try {
await _audioPlayer.setFilePath(recordFilePath);
_audioPlayer.play();
} catch (ex) {
_isAudioHaveError = true;
}
} else {
Utils.showToast("يجب عليك التسجيل أولا");
}
}
Future<String> getFilePath() async {
Directory storageDirectory = await getApplicationDocumentsDirectory();
String sdPath = storageDirectory.path + "/record";
var d = Directory(sdPath);
if (!d.existsSync()) {
d.createSync(recursive: true);
}
return sdPath + "/test.mp3";
}
@override
Widget build(BuildContext context) {
return Stack(
alignment: Alignment.bottomCenter,
children: [
Container(
margin: EdgeInsets.only(top: 4, bottom: 20),
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: Row(
mainAxisSize: MainAxisSize.min,
children: [
SvgPicture.asset(
"assets/icons/mic_icon.svg",
width: 25,
height: 25,
),
SizedBox(width: 12),
Text(
"سجل الآية بصوتك",
style: TextStyle(fontSize: 18, color: Colors.white),
),
],
),
),
InkWell(
onTap: () {
if (_isRecording) {
stopRecord();
} else {
startRecord();
}
},
child: SvgPicture.asset(
_isRecording ? "assets/icons/recording_on.svg" : "assets/icons/recording_off.svg",
width: 60,
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>(
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 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);
}
}
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();
});
},
),
],
),
)
],
),
),
Positioned(
bottom: 0,
child: InkWell(
borderRadius: BorderRadius.circular(30),
onTap: () async {
if (await _requestStoragePermission()) {
if (recordFilePath != null && File(recordFilePath).existsSync()) {
saveToPhoneStorage(recordFilePath);
} else {
Utils.showToast("يجب عليك تسجيل صوتك أولا");
}
} else {
Utils.showToast("يجب أن تمنح الإذن لتنزيل التسجيل");
}
},
child: Container(
height: 40,
padding: EdgeInsets.only(left: 24, right: 24),
alignment: Alignment.centerRight,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: ColorConsts.gradientPink,
gradient: LinearGradient(
stops: [0.0, 0.5],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [ColorConsts.gradientPink, ColorConsts.gradientOrange],
),
),
child: Text(
"تنزيل التسجيل",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14, color: Colors.white, height: 1.5),
),
),
),
),
],
);
}
Future<bool> _requestStoragePermission() async {
Map<Permission, PermissionStatus> statuses = await [
Permission.storage,
].request();
return statuses[Permission.storage].isGranted;
}
String _durationTime(Duration duration) {
if (duration == null) {
return "00:00";
}
String twoDigits(int n) => n.toString().padLeft(2, "0");
String twoDigitMinutes = twoDigits(duration.inMinutes.remainder(60));
String twoDigitSeconds = twoDigits(duration.inSeconds.remainder(60));
return "$twoDigitMinutes:$twoDigitSeconds";
}
void saveToPhoneStorage(String filePath) async {
File file = File(filePath);
Directory storageDirectory = await getExternalStorageDirectory();
String storagePath = storageDirectory.path;
if (storagePath.contains("/Android/data")) {
storagePath = storagePath.substring(0, storagePath.indexOf("/Android/data"));
}
storagePath += "/tangheem/record/";
var d = Directory(storagePath);
if (!d.existsSync()) {
d.createSync(recursive: true);
}
storagePath += "Tangheem${DateTime.now().millisecondsSinceEpoch}.mp3";
await file.copy(storagePath);
Utils.showToast("تم التنزيل");
}
}

@ -11,6 +11,7 @@ class TextHighLightWidget extends StatelessWidget {
final TextStyle style; final TextStyle style;
final TextAlign textAlign; final TextAlign textAlign;
final Color highLightColor; final Color highLightColor;
final double highLightFontSize;
final Function(String) onTap; final Function(String) onTap;
final Function(String) onAyaTap; final Function(String) onAyaTap;
@ -23,6 +24,7 @@ class TextHighLightWidget extends StatelessWidget {
this.highlights, this.highlights,
this.highLightColor = ColorConsts.secondaryOrange, this.highLightColor = ColorConsts.secondaryOrange,
this.style = const TextStyle(), this.style = const TextStyle(),
this.highLightFontSize = 18,
this.onTap, this.onTap,
this.onAyaTap}); this.onAyaTap});
@ -97,7 +99,7 @@ class TextHighLightWidget extends StatelessWidget {
if (style.color == null) { if (style.color == null) {
return TextSpan( return TextSpan(
text: value, text: value,
style: style.copyWith(color: highLightColor, fontSize: 18), style: style.copyWith(color: highLightColor, fontSize: highLightFontSize),
recognizer: TapGestureRecognizer() recognizer: TapGestureRecognizer()
..onTap = () { ..onTap = () {
if (onTap != null) { if (onTap != null) {

@ -39,6 +39,7 @@ dependencies:
shared_preferences: ^2.0.5 shared_preferences: ^2.0.5
url_launcher: ^6.0.3 url_launcher: ^6.0.3
flutter_slidable: ^0.6.0 flutter_slidable: ^0.6.0
record_mp3: ^2.1.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:

Loading…
Cancel
Save