-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Improve bottom bar and file downloads (#158)
* feat: change bottom nav bar style to fixed * refactor: migrate file store to null safety * fix: illegal access firebase for auto roll call while feature not enabled * refactor: migrate toast to null safety * refactor: migrate permission util to null safety * refactor: migrate file download to null safety, and add dialog while download complete * refactor: migrade iplus file page to null safety * chore: remove unneeded aos permissions
- Loading branch information
1 parent
8f7cae4
commit d504e08
Showing
8 changed files
with
198 additions
and
202 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,118 +1,125 @@ | ||
// TODO: remove sdk version selector after migrating to null-safety. | ||
// @dart=2.10 | ||
// ignore_for_file: import_of_legacy_library_into_null_safe | ||
|
||
import 'dart:convert'; | ||
|
||
import 'package:awesome_dialog/awesome_dialog.dart'; | ||
import 'package:dio/dio.dart'; | ||
import 'package:flutter_app/debug/log/log.dart'; | ||
import 'package:flutter_app/src/connector/core/dio_connector.dart'; | ||
import 'package:flutter_app/src/notifications/notifications.dart'; | ||
import 'package:flutter_app/src/r.dart'; | ||
import 'package:flutter_app/src/util/file_utils.dart'; | ||
import 'package:flutter_app/ui/other/error_dialog.dart'; | ||
|
||
import 'file_store.dart'; | ||
|
||
class FileDownload { | ||
static Future<void> download(String url, dirName, [String name = "", String referer]) async { | ||
String path = await FileStore.getDownloadDir(dirName); //取得下載路徑 | ||
String realFileName; | ||
String fileExtension; | ||
static Future<void> download(String url, dirName, [String name = "", String? referer]) async { | ||
final path = await FileStore.getDownloadDir(dirName); | ||
String? realFileName = ""; | ||
String? fileExtension = ""; | ||
referer = referer ?? url; | ||
Log.d("file download \n url: $url \n referer: $referer"); | ||
//顯示下載通知窗 | ||
ReceivedNotification value = | ||
ReceivedNotification(title: name, body: R.current.prepareDownload, payload: null); //通知窗訊息 | ||
CancelToken cancelToken; //取消下載用 | ||
ProgressCallback onReceiveProgress; //下載進度回調 | ||
final value = ReceivedNotification(title: name, body: R.current.prepareDownload, payload: null); //通知窗訊息 | ||
final cancelToken = CancelToken(); | ||
await Notifications.instance.showIndeterminateProgressNotification(value); | ||
//顯示下載進度通知窗 | ||
value.title = name; | ||
|
||
int nowSize = 0; | ||
onReceiveProgress = (int count, int total) async { | ||
onReceiveProgress(int count, int total) { | ||
value.body = FileUtils.formatBytes(count, 2); | ||
if ((nowSize + 1024 * 128) > count && nowSize != 0) { | ||
//128KB顯示一次 | ||
return; | ||
} | ||
nowSize = count; | ||
if (count < total) { | ||
Notifications.instance.showProgressNotification(value, 100, (count * 100 / total).round()); //顯示下載進度 | ||
} else { | ||
Notifications.instance.showIndeterminateProgressNotification(value); //顯示下載進度 | ||
Notifications.instance.showIndeterminateProgressNotification(value); | ||
} | ||
}; | ||
//開始下載檔案 | ||
DioConnector.instance.download(url, (Headers responseHeaders) { | ||
Map<String, List<String>> headers = responseHeaders.map; | ||
if (headers.containsKey("content-disposition")) { | ||
//代表有名字 | ||
List<String> name = headers["content-disposition"]; | ||
RegExp exp = RegExp("['|\"](?<name>.+)['|\"]"); //尋找 'name' , "name" 的name | ||
RegExpMatch matches = exp.firstMatch(name[0]); | ||
realFileName = matches.group(1); | ||
} else if (headers.containsKey("content-type")) { | ||
List<String> name = headers["content-type"]; | ||
if (name[0].toLowerCase().contains("pdf")) { | ||
//是application/pdf | ||
realFileName = '.pdf'; | ||
} | ||
|
||
// This flag is used to prevent the dialog from being displayed multiple times. | ||
bool hasError = false; | ||
await DioConnector.instance.download( | ||
url, | ||
(responseHeaders) { | ||
final Map<String, List<String>> headers = responseHeaders.map; | ||
if (headers.containsKey("content-disposition")) { | ||
final name = headers["content-disposition"]; | ||
final exp = RegExp("['|\"](?<name>.+)['|\"]"); | ||
final matches = name != null ? exp.firstMatch(name[0]) : null; | ||
realFileName = matches?.group(1); | ||
} else if (headers.containsKey("content-type")) { | ||
final name = headers["content-type"]; | ||
if (name?[0].toLowerCase().contains("pdf") == true) { | ||
realFileName = '.pdf'; | ||
} | ||
} | ||
} | ||
if (!name.contains(".")) { | ||
//代表名字不包含副檔名 | ||
if (realFileName != null) { | ||
//代表可以從網路取得副檔名 | ||
fileExtension = realFileName.split(".").reversed.toList()[0]; | ||
realFileName = "$name.$fileExtension"; | ||
} else { | ||
//嘗試使用網址後面找出附檔名 | ||
String maybeName = url.split("/").toList().last; | ||
if (maybeName.contains(".")) { | ||
fileExtension = maybeName.split(".").toList().last; | ||
if (!name.contains(".")) { | ||
if (realFileName != null) { | ||
fileExtension = realFileName?.split(".").reversed.toList()[0]; | ||
realFileName = "$name.$fileExtension"; | ||
} else { | ||
final maybeName = url.split("/").toList().last; | ||
if (maybeName.contains(".")) { | ||
fileExtension = maybeName.split(".").toList().last; | ||
realFileName = "$name.$fileExtension"; | ||
} | ||
} | ||
} else { | ||
final List<String> s = name.split("."); | ||
s.removeLast(); | ||
if (realFileName != null && realFileName?.contains(".") == true) { | ||
realFileName = '${s.join()}.${realFileName?.split(".").last ?? ""}'; | ||
} | ||
//realFileName = name + "." + fileExtension; | ||
} | ||
} else { | ||
//代表包含. | ||
List<String> s = name.split("."); | ||
s.removeLast(); | ||
if (realFileName != null && realFileName.contains(".")) { | ||
realFileName = '${s.join()}.${realFileName.split(".").last}'; | ||
} | ||
} | ||
realFileName = realFileName ?? name; //如果還是沒有找到副檔名直接使用原始名稱 | ||
//print(path + "/" + realFileName); | ||
return "$path/$realFileName"; | ||
}, progressCallback: onReceiveProgress, cancelToken: cancelToken, header: {"referer": referer}).whenComplete( | ||
() async { | ||
//顯示下載萬完成通知窗 | ||
await Notifications.instance.cancelNotification(value.id); | ||
value.body = R.current.downloadComplete; | ||
value.id = Notifications.instance.notificationId; //取得新的id | ||
String filePath = '$path/$realFileName'; | ||
int id = value.id; | ||
value.payload = json.encode({ | ||
"type": "download_complete", | ||
"path": filePath, | ||
"id": id, | ||
}); | ||
await Notifications.instance.showNotification(value); //顯示下載完成 | ||
realFileName = realFileName ?? name; | ||
return "$path/$realFileName"; | ||
}, | ||
progressCallback: onReceiveProgress, | ||
cancelToken: cancelToken, | ||
header: {"referer": referer}, | ||
).catchError( | ||
(onError) async { | ||
//顯示下載萬完成通知窗 | ||
hasError = true; | ||
Log.d(onError.toString()); | ||
await Future.delayed(const Duration(milliseconds: 100)); | ||
Notifications.instance.cancelNotification(value.id); | ||
value.body = "下載失敗"; | ||
value.id = Notifications.instance.notificationId; //取得新的id | ||
int id = value.id; | ||
|
||
value.body = R.current.downloadError; | ||
value.id = Notifications.instance.notificationId; | ||
value.payload = json.encode({ | ||
"type": "download_fail", | ||
"id": id, | ||
"id": value.id, | ||
}); | ||
await Notifications.instance.showNotification(value); //顯示下載完成 | ||
|
||
await Notifications.instance.showNotification(value); | ||
ErrorDialog(ErrorDialogParameter( | ||
desc: realFileName, | ||
title: R.current.downloadError, | ||
offCancelBtn: true, | ||
dialogType: DialogType.warning, | ||
)).show(); | ||
}, | ||
); | ||
|
||
if (!hasError) { | ||
await Notifications.instance.cancelNotification(value.id); | ||
value.body = R.current.downloadComplete; | ||
value.id = Notifications.instance.notificationId; | ||
value.payload = json.encode({ | ||
"type": "download_complete", | ||
"path": '$path/$realFileName', | ||
"id": value.id, | ||
}); | ||
await Notifications.instance.showNotification(value); | ||
ErrorDialog(ErrorDialogParameter( | ||
desc: realFileName, | ||
title: R.current.downloadComplete, | ||
offCancelBtn: true, | ||
dialogType: DialogType.success, | ||
)).show(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,17 @@ | ||
// TODO: remove sdk version selector after migrating to null-safety. | ||
// @dart=2.10 | ||
import 'package:flutter/material.dart'; | ||
import 'package:flutter_app/src/config/app_colors.dart'; | ||
import 'package:fluttertoast/fluttertoast.dart'; | ||
|
||
class MyToast { | ||
static void show(String message) { | ||
Fluttertoast.showToast( | ||
msg: message, | ||
toastLength: Toast.LENGTH_SHORT, | ||
gravity: ToastGravity.BOTTOM, | ||
timeInSecForIosWeb: 1, | ||
backgroundColor: AppColors.mainColor, | ||
textColor: Colors.white, | ||
fontSize: 16.0); | ||
msg: message, | ||
toastLength: Toast.LENGTH_SHORT, | ||
gravity: ToastGravity.BOTTOM, | ||
timeInSecForIosWeb: 1, | ||
backgroundColor: AppColors.mainColor, | ||
textColor: Colors.white, | ||
fontSize: 16.0, | ||
); | ||
} | ||
} |
Oops, something went wrong.