|
|
|
|
@ -1,14 +1,14 @@
|
|
|
|
|
import 'dart:convert';
|
|
|
|
|
import 'dart:io';
|
|
|
|
|
import 'dart:math' as math;
|
|
|
|
|
import 'dart:typed_data';
|
|
|
|
|
import 'dart:ui' as ui;
|
|
|
|
|
|
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
|
import 'package:flutter/rendering.dart';
|
|
|
|
|
import 'package:flutter/services.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:path_provider/path_provider.dart';
|
|
|
|
|
import 'package:permission_handler/permission_handler.dart';
|
|
|
|
|
import 'package:tangheem/classes/colors.dart';
|
|
|
|
|
import 'package:tangheem/classes/consts.dart';
|
|
|
|
|
@ -196,17 +196,14 @@ class _AyaPlayerWidgetState extends State<AyaPlayerWidget> {
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
commonIconButton("assets/icons/download_aya.svg", () async {
|
|
|
|
|
if (await _requestPermission()) {
|
|
|
|
|
if (await _saveAya()) {
|
|
|
|
|
Utils.showToast("تم حفظ الآية بنجاح");
|
|
|
|
|
if (widget.voiceNoteList?.isNotEmpty ?? false)
|
|
|
|
|
commonIconButton("assets/icons/download_aya.svg", () async {
|
|
|
|
|
if (await _requestPermission()) {
|
|
|
|
|
saveToPhoneStorage(widget.voiceNoteList[_player.currentIndex].exposeFilePath, widget.voiceNoteList[_player.currentIndex].userName ?? "");
|
|
|
|
|
} else {
|
|
|
|
|
Utils.showToast("خطأ في حفظ الآية");
|
|
|
|
|
Utils.showToast("يجب اعطاء الاذن لتنزيل الآية");
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
Utils.showToast("يجب اعطاء الاذن لتنزيل الآية");
|
|
|
|
|
}
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
SizedBox(height: 8),
|
|
|
|
|
@ -311,27 +308,82 @@ class _AyaPlayerWidgetState extends State<AyaPlayerWidget> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<bool> _requestPermission() async {
|
|
|
|
|
Map<Permission, PermissionStatus> statuses = await [
|
|
|
|
|
Permission.storage,
|
|
|
|
|
].request();
|
|
|
|
|
Map<Permission, PermissionStatus> statuses = await [Permission.storage].request();
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
try {
|
|
|
|
|
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);
|
|
|
|
|
downloadFile(ApiConsts.baseUrl + filePath, storagePath, onResponse: (isSuccess) {
|
|
|
|
|
Utils.hideLoading(context);
|
|
|
|
|
return result["isSuccess"];
|
|
|
|
|
} catch (ex) {
|
|
|
|
|
Future.delayed(Duration(seconds: 1), () {
|
|
|
|
|
Utils.hideLoading(context);
|
|
|
|
|
});
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (isSuccess) {
|
|
|
|
|
Utils.showToast("تم حفظ الآية بنجاح");
|
|
|
|
|
} else {
|
|
|
|
|
Utils.showToast("خطأ في حفظ الآية");
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|