tangheem audio download feature added. & home icon added

development
Sikander Saleem 4 years ago
parent 1737d2541e
commit 63779374fa

@ -11,17 +11,17 @@
<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
<application <application
android:icon="@mipmap/ic_launcher"
android:label="Tangheem" android:label="Tangheem"
android:roundIcon="@mipmap/ic_launcher_round"
android:usesCleartextTraffic="true"
android:requestLegacyExternalStorage="true" android:requestLegacyExternalStorage="true"
android:icon="@mipmap/ic_launcher"> android:roundIcon="@mipmap/ic_launcher_round"
android:usesCleartextTraffic="true">
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true" android:hardwareAccelerated="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:windowSoftInputMode="adjustResize"> android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as <!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user the Android process has started. This theme is visible to the user
@ -29,8 +29,7 @@
to determine the Window background behind the Flutter UI. --> to determine the Window background behind the Flutter UI. -->
<meta-data <meta-data
android:name="io.flutter.embedding.android.NormalTheme" android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme" android:resource="@style/NormalTheme" />
/>
<!-- Displays an Android View that continues showing the launch screen <!-- Displays an Android View that continues showing the launch screen
Drawable until Flutter paints its first frame, then this splash Drawable until Flutter paints its first frame, then this splash
screen fades out. A splash screen is useful to avoid any visual screen fades out. A splash screen is useful to avoid any visual
@ -38,8 +37,7 @@
Flutter's first frame. --> Flutter's first frame. -->
<meta-data <meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable" android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background" android:resource="@drawable/launch_background" />
/>
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />

@ -84,6 +84,12 @@ class TangheemUserApiClient {
return await ApiClient().postJsonForObject((json) => AyatTangheemTypeMapped.fromJson(json), url, postParams); return await ApiClient().postJsonForObject((json) => AyatTangheemTypeMapped.fromJson(json), url, postParams);
} }
Future<AyatTangheemTypeMapped> getAyaTangheemTypeMappedFor(int surahNo, String numberInSurahs, String tangheemTypeId) async {
String url = "${ApiConsts.tangheemUsers}AyatTangheemTypeMapped_Get";
var postParams = {"surahNo": surahNo, "numberInSurahs": numberInSurahs, "tangheemTypeId": tangheemTypeId};
return await ApiClient().postJsonForObject((json) => AyatTangheemTypeMapped.fromJson(json), url, postParams);
}
Future<AyatTangheemTypeMapped> ayahBaseTextGet(String tangheemTypeName, String ayaText, int itemsPerPage, int currentPageNo) async { Future<AyatTangheemTypeMapped> ayahBaseTextGet(String tangheemTypeName, String ayaText, int itemsPerPage, int currentPageNo) async {
String url = "${ApiConsts.tangheemUsers}AyahBaseText_Get"; String url = "${ApiConsts.tangheemUsers}AyahBaseText_Get";
var postParams = {}; var postParams = {};
@ -139,9 +145,7 @@ class TangheemUserApiClient {
Future<DiscussionModel> getDiscussionByTangheemID(int pageNumber, String tangheemID) async { Future<DiscussionModel> getDiscussionByTangheemID(int pageNumber, String tangheemID) async {
String url = "${ApiConsts.tangheemUsers}Discussion_Get"; String url = "${ApiConsts.tangheemUsers}Discussion_Get";
var postParams = {"itemsPerPage": 5, "currentPageNo": pageNumber, "ayaTangheemTypeId": tangheemID}; var postParams = {"itemsPerPage": 5, "statusId": 2, "ayaTangheemTypeId": tangheemID};
postParams["itemsPerPage"] = null;
postParams["currentPageNo"] = null;
return await ApiClient().postJsonForObject((json) => DiscussionModel.fromJson(json), url, postParams); return await ApiClient().postJsonForObject((json) => DiscussionModel.fromJson(json), url, postParams);
} }

@ -15,6 +15,7 @@ import 'package:tangheem/models/quick_links_model.dart';
import 'package:tangheem/ui/dialogs/change_password_dialog.dart'; import 'package:tangheem/ui/dialogs/change_password_dialog.dart';
import 'package:tangheem/ui/screens/bookmark_screen.dart'; import 'package:tangheem/ui/screens/bookmark_screen.dart';
import 'package:tangheem/ui/screens/content_info_screen.dart'; import 'package:tangheem/ui/screens/content_info_screen.dart';
import 'package:tangheem/ui/screens/home_screen.dart';
import 'package:tangheem/ui/screens/login_screen.dart'; import 'package:tangheem/ui/screens/login_screen.dart';
import 'package:tangheem/ui/screens/pdf_viewer_screen.dart'; import 'package:tangheem/ui/screens/pdf_viewer_screen.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
@ -134,6 +135,14 @@ class _CommonAppbarState extends State<CommonAppbar> {
} }
}, },
), ),
if (!widget.showDrawer)
IconButton(
icon: Icon(widget.showDrawer ? Icons.home : Icons.home, color: ColorConsts.textGrey),
padding: EdgeInsets.only(left: 16),
onPressed: () {
Navigator.popUntil(context, ModalRoute.withName(HomeScreen.routeName));
},
),
Expanded(child: SizedBox()), Expanded(child: SizedBox()),
Hero( Hero(
tag: "logo", tag: "logo",

@ -86,6 +86,19 @@ class _TangheemScreenState extends State<TangheemScreen> {
setState(() {}); setState(() {});
} }
void getTangheemDataForTangheem(int surahNo, String numberInSurahs, String tangheemTypeId, String ayaTangheemTypeId) async {
Utils.showLoading(context);
try {
AyatTangheemTypeMapped _ayatTangheemTypeMapped = await TangheemUserApiClient().getAyaTangheemTypeMappedFor(surahNo, numberInSurahs, tangheemTypeId);
TangheemDetailParams tangheem = TangheemDetailParams(selectedTangheemTypeId: ayaTangheemTypeId, ayatTangheemTypeMappedDataList: _ayatTangheemTypeMapped.data ?? []);
Utils.hideLoading(context);
Navigator.pushNamed(context, TangheemDetailScreen.routeName, arguments: tangheem);
} catch (ex) {
if (mounted) Utils.handleException(ex, null);
Utils.hideLoading(context);
}
}
@override @override
void dispose() { void dispose() {
super.dispose(); super.dispose();
@ -108,6 +121,7 @@ class _TangheemScreenState extends State<TangheemScreen> {
itemBuilder: (context, index) { itemBuilder: (context, index) {
return InkWell( return InkWell(
onTap: () { onTap: () {
if (widget.tangheemQuery == null) {
List<AyatTangheemTypeMappedData> list = <AyatTangheemTypeMappedData>[] + _dataList; List<AyatTangheemTypeMappedData> list = <AyatTangheemTypeMappedData>[] + _dataList;
var removedData = _dataList[index]; var removedData = _dataList[index];
list.remove(removedData); list.remove(removedData);
@ -115,6 +129,10 @@ class _TangheemScreenState extends State<TangheemScreen> {
list = list?.where((element) => (element.ayahNos.contains(removedData.ayahNos)) && (element.tangheemTypeId == removedData.tangheemTypeId))?.toList() ?? []; list = list?.where((element) => (element.ayahNos.contains(removedData.ayahNos)) && (element.tangheemTypeId == removedData.tangheemTypeId))?.toList() ?? [];
TangheemDetailParams tangheem = TangheemDetailParams(selectedTangheemTypeId: removedData.ayaTangheemTypeId, ayatTangheemTypeMappedDataList: list); TangheemDetailParams tangheem = TangheemDetailParams(selectedTangheemTypeId: removedData.ayaTangheemTypeId, ayatTangheemTypeMappedDataList: list);
Navigator.pushNamed(context, TangheemDetailScreen.routeName, arguments: tangheem); Navigator.pushNamed(context, TangheemDetailScreen.routeName, arguments: tangheem);
} else {
var removedData = _dataList[index];
getTangheemDataForTangheem(removedData.surahNo, removedData.ayatNumberInSurahs, removedData.tangheemTypeId, removedData.ayaTangheemTypeId);
}
}, },
borderRadius: BorderRadius.circular(4), borderRadius: BorderRadius.circular(4),
child: Container( child: Container(

@ -1,14 +1,14 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:io';
import 'dart:math' as math; import 'dart:math' as math;
import 'dart:typed_data'; import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:image_gallery_saver/image_gallery_saver.dart'; import 'package:http/http.dart' as http;
import 'package:just_audio/just_audio.dart'; import 'package:just_audio/just_audio.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
import 'package:tangheem/classes/colors.dart'; import 'package:tangheem/classes/colors.dart';
import 'package:tangheem/classes/consts.dart'; import 'package:tangheem/classes/consts.dart';
@ -196,13 +196,10 @@ class _AyaPlayerWidgetState extends State<AyaPlayerWidget> {
], ],
), ),
), ),
if (widget.voiceNoteList?.isNotEmpty ?? false)
commonIconButton("assets/icons/download_aya.svg", () async { commonIconButton("assets/icons/download_aya.svg", () async {
if (await _requestPermission()) { if (await _requestPermission()) {
if (await _saveAya()) { saveToPhoneStorage(widget.voiceNoteList[_player.currentIndex].exposeFilePath, widget.voiceNoteList[_player.currentIndex].userName ?? "");
Utils.showToast("تم حفظ الآية بنجاح");
} else {
Utils.showToast("خطأ في حفظ الآية");
}
} else { } else {
Utils.showToast("يجب اعطاء الاذن لتنزيل الآية"); Utils.showToast("يجب اعطاء الاذن لتنزيل الآية");
} }
@ -311,27 +308,82 @@ class _AyaPlayerWidgetState extends State<AyaPlayerWidget> {
} }
Future<bool> _requestPermission() async { Future<bool> _requestPermission() async {
Map<Permission, PermissionStatus> statuses = await [ Map<Permission, PermissionStatus> statuses = await [Permission.storage].request();
Permission.storage,
].request();
return statuses[Permission.storage].isGranted; return statuses[Permission.storage].isGranted;
} }
Future<bool> _saveAya() async { void saveToPhoneStorage(String filePath, String name) async {
Directory storageDirectory;
if (Platform.isAndroid) {
storageDirectory = await getExternalStorageDirectory();
} else if (Platform.isIOS) {
storageDirectory = await getApplicationDocumentsDirectory();
} else {
return;
}
String storagePath = storageDirectory.path;
if (storagePath.contains("/Android/data")) {
storagePath = storagePath.substring(0, storagePath.indexOf("/Android/data"));
}
storagePath += "/Download/Tangheem/";
var d = Directory(storagePath);
if (!d.existsSync()) {
d.createSync(recursive: true);
}
storagePath += "Tangheem-$name-${DateTime.now().millisecondsSinceEpoch}${filePath.substring(filePath.lastIndexOf('.'), filePath.length)}";
Utils.showLoading(context); Utils.showLoading(context);
try { downloadFile(ApiConsts.baseUrl + filePath, storagePath, onResponse: (isSuccess) {
RenderRepaintBoundary boundary = widget.globalKey.currentContext.findRenderObject();
ui.Image image = await boundary.toImage(pixelRatio: 3.0);
ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
final result = await ImageGallerySaver.saveImage(byteData.buffer.asUint8List(), quality: 100);
Utils.hideLoading(context);
return result["isSuccess"];
} catch (ex) {
Future.delayed(Duration(seconds: 1), () {
Utils.hideLoading(context); Utils.hideLoading(context);
if (isSuccess) {
Utils.showToast("تم حفظ الآية بنجاح");
} else {
Utils.showToast("خطأ في حفظ الآية");
}
}); });
return false;
} }
void downloadFile(String url, String path, {Function(bool) onResponse}) {
var httpClient = http.Client();
var request = http.Request('GET', Uri.parse(url));
var response = httpClient.send(request);
String dir = path;
List<List<int>> chunks = [];
int downloaded = 0;
int lastVal;
response.asStream().listen((http.StreamedResponse r) {
r.stream.listen((List<int> chunk) {
debugPrint('downloadPercentage: ${downloaded / r.contentLength * 100}');
lastVal = (downloaded / r.contentLength * 100).toInt();
chunks.add(chunk);
downloaded += chunk.length;
}, onDone: () async {
debugPrint('downloadPercentage: ${downloaded / r.contentLength * 100}');
if (lastVal == 0) {
onResponse(false);
return;
}
// Save the file
File file = new File('$dir');
final Uint8List bytes = Uint8List(r.contentLength);
int offset = 0;
for (List<int> chunk in chunks) {
bytes.setRange(offset, offset + chunk.length, chunk);
offset += chunk.length;
}
await file.writeAsBytes(bytes);
onResponse(true);
return;
}, onError: (ex) {
debugPrint("onError:$ex");
}, cancelOnError: true);
}).onError((ex) {
debugPrint("onError:$ex");
onResponse(false);
});
} }
} }

@ -279,9 +279,7 @@ class _AyaRecordWidgetState extends State<AyaRecordWidget> {
} }
Future<bool> _requestStoragePermission() async { Future<bool> _requestStoragePermission() async {
Map<Permission, PermissionStatus> statuses = await [ Map<Permission, PermissionStatus> statuses = await [Permission.storage].request();
Permission.storage,
].request();
return statuses[Permission.storage].isGranted; return statuses[Permission.storage].isGranted;
} }
@ -310,12 +308,13 @@ class _AyaRecordWidgetState extends State<AyaRecordWidget> {
if (storagePath.contains("/Android/data")) { if (storagePath.contains("/Android/data")) {
storagePath = storagePath.substring(0, storagePath.indexOf("/Android/data")); storagePath = storagePath.substring(0, storagePath.indexOf("/Android/data"));
} }
storagePath += "/tangheem/record/"; storagePath += "/Download/Tangheem/";
var d = Directory(storagePath); var d = Directory(storagePath);
if (!d.existsSync()) { if (!d.existsSync()) {
d.createSync(recursive: true); d.createSync(recursive: true);
} }
storagePath += "Tangheem${DateTime.now().millisecondsSinceEpoch}.mp3"; storagePath += "Tangheem${DateTime.now().millisecondsSinceEpoch}.mp3";
print("storagePath:$storagePath");
await file.copy(storagePath); await file.copy(storagePath);
Utils.showToast("تم التنزيل"); Utils.showToast("تم التنزيل");
} }

Loading…
Cancel
Save