Check directory exists when downloading
This commit is contained in:
parent
ac91c104d7
commit
a301b0e839
|
|
@ -34,9 +34,9 @@ import 'package:invoiceninja_flutter/redux/vendor/vendor_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart';
|
import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/dialogs.dart';
|
import 'package:invoiceninja_flutter/utils/dialogs.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/files.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
|
||||||
import 'package:pinch_zoom/pinch_zoom.dart';
|
import 'package:pinch_zoom/pinch_zoom.dart';
|
||||||
import 'package:printing/printing.dart';
|
import 'package:printing/printing.dart';
|
||||||
|
|
||||||
|
|
@ -321,7 +321,7 @@ void handleDocumentAction(
|
||||||
}
|
}
|
||||||
|
|
||||||
final store = StoreProvider.of<AppState>(context!);
|
final store = StoreProvider.of<AppState>(context!);
|
||||||
final localization = AppLocalization.of(context);
|
final localization = AppLocalization.of(context)!;
|
||||||
final documentIds = documents.map((document) => document.id).toList();
|
final documentIds = documents.map((document) => document.id).toList();
|
||||||
final document = store.state.documentState.map[documentIds.first]!;
|
final document = store.state.documentState.map[documentIds.first]!;
|
||||||
|
|
||||||
|
|
@ -331,19 +331,19 @@ void handleDocumentAction(
|
||||||
break;
|
break;
|
||||||
case EntityAction.restore:
|
case EntityAction.restore:
|
||||||
final message = documentIds.length > 1
|
final message = documentIds.length > 1
|
||||||
? localization!.restoredDocuments
|
? localization.restoredDocuments
|
||||||
.replaceFirst(':value', ':count')
|
.replaceFirst(':value', ':count')
|
||||||
.replaceFirst(':count', documentIds.length.toString())
|
.replaceFirst(':count', documentIds.length.toString())
|
||||||
: localization!.restoredDocument;
|
: localization.restoredDocument;
|
||||||
store.dispatch(RestoreDocumentRequest(
|
store.dispatch(RestoreDocumentRequest(
|
||||||
snackBarCompleter<Null>(message), documentIds));
|
snackBarCompleter<Null>(message), documentIds));
|
||||||
break;
|
break;
|
||||||
case EntityAction.archive:
|
case EntityAction.archive:
|
||||||
final message = documentIds.length > 1
|
final message = documentIds.length > 1
|
||||||
? localization!.archivedDocuments
|
? localization.archivedDocuments
|
||||||
.replaceFirst(':value', ':count')
|
.replaceFirst(':value', ':count')
|
||||||
.replaceFirst(':count', documentIds.length.toString())
|
.replaceFirst(':count', documentIds.length.toString())
|
||||||
: localization!.archivedDocument;
|
: localization.archivedDocument;
|
||||||
store.dispatch(ArchiveDocumentRequest(
|
store.dispatch(ArchiveDocumentRequest(
|
||||||
snackBarCompleter<Null>(message), documentIds));
|
snackBarCompleter<Null>(message), documentIds));
|
||||||
break;
|
break;
|
||||||
|
|
@ -386,7 +386,7 @@ void handleDocumentAction(
|
||||||
DownloadDocumentsRequest(
|
DownloadDocumentsRequest(
|
||||||
documentIds: documentIds,
|
documentIds: documentIds,
|
||||||
completer: snackBarCompleter<Null>(
|
completer: snackBarCompleter<Null>(
|
||||||
localization!.exportedData,
|
localization.exportedData,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
@ -402,7 +402,7 @@ void handleDocumentAction(
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
child: Text(localization!.close.toUpperCase())),
|
child: Text(localization.close.toUpperCase())),
|
||||||
],
|
],
|
||||||
content: document.isImage
|
content: document.isImage
|
||||||
? PinchZoom(
|
? PinchZoom(
|
||||||
|
|
@ -440,27 +440,26 @@ void handleDocumentAction(
|
||||||
WebUtils.downloadBinaryFile(document!.name, document.data!);
|
WebUtils.downloadBinaryFile(document!.name, document.data!);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
final directory = await (isDesktopOS()
|
final directory = await getAppDownloadDirectory();
|
||||||
? getDownloadsDirectory() as FutureOr<file.Directory>
|
if (directory != null) {
|
||||||
: getApplicationDocumentsDirectory());
|
String filePath =
|
||||||
|
'$directory/${file.Platform.pathSeparator}${document!.name}';
|
||||||
|
|
||||||
String filePath =
|
if (file.File(filePath).existsSync()) {
|
||||||
'${directory.path}${file.Platform.pathSeparator}${document!.name}';
|
final extension = document.name.split('.').last;
|
||||||
|
final timestamp = DateTime.now().millisecondsSinceEpoch;
|
||||||
|
filePath = filePath.replaceFirst(
|
||||||
|
'.$extension', '_$timestamp.$extension');
|
||||||
|
}
|
||||||
|
|
||||||
if (file.File(filePath).existsSync()) {
|
await File(filePath).writeAsBytes(document.data!);
|
||||||
final extension = document.name.split('.').last;
|
|
||||||
final timestamp = DateTime.now().millisecondsSinceEpoch;
|
|
||||||
filePath =
|
|
||||||
filePath.replaceFirst('.$extension', '_$timestamp.$extension');
|
|
||||||
}
|
|
||||||
|
|
||||||
await File(filePath).writeAsBytes(document.data!);
|
if (isDesktopOS()) {
|
||||||
|
showToast(localization.fileSavedInPath
|
||||||
if (isDesktopOS()) {
|
.replaceFirst(':path', directory));
|
||||||
showToast(localization!.fileSavedInPath
|
} else {
|
||||||
.replaceFirst(':path', directory.path));
|
await Share.shareXFiles([XFile(filePath)]);
|
||||||
} else {
|
}
|
||||||
await Share.shareXFiles([XFile(filePath)]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,8 @@ import 'package:invoiceninja_flutter/ui/app/buttons/elevated_button.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/dialogs/error_dialog.dart';
|
import 'package:invoiceninja_flutter/ui/app/dialogs/error_dialog.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/forms/date_picker.dart';
|
import 'package:invoiceninja_flutter/ui/app/forms/date_picker.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/multiselect.dart';
|
import 'package:invoiceninja_flutter/ui/app/multiselect.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/files.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/formatting.dart';
|
import 'package:invoiceninja_flutter/utils/formatting.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
|
||||||
import 'package:printing/printing.dart';
|
import 'package:printing/printing.dart';
|
||||||
|
|
||||||
// Project imports:
|
// Project imports:
|
||||||
|
|
@ -352,16 +352,14 @@ class _ClientPdfViewState extends State<ClientPdfView> {
|
||||||
WebUtils.downloadBinaryFile(
|
WebUtils.downloadBinaryFile(
|
||||||
fileName, _response!.bodyBytes);
|
fileName, _response!.bodyBytes);
|
||||||
} else {
|
} else {
|
||||||
final directory = await (isDesktopOS()
|
final directory = await getAppDownloadDirectory();
|
||||||
? getDownloadsDirectory()
|
|
||||||
: getApplicationDocumentsDirectory());
|
|
||||||
|
|
||||||
if (directory == null) {
|
if (directory == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String filePath =
|
String filePath =
|
||||||
'${directory.path}${file.Platform.pathSeparator}$fileName';
|
'$directory${file.Platform.pathSeparator}$fileName';
|
||||||
|
|
||||||
if (file.File(filePath).existsSync()) {
|
if (file.File(filePath).existsSync()) {
|
||||||
final timestamp =
|
final timestamp =
|
||||||
|
|
@ -375,7 +373,7 @@ class _ClientPdfViewState extends State<ClientPdfView> {
|
||||||
|
|
||||||
if (isDesktopOS()) {
|
if (isDesktopOS()) {
|
||||||
showToast(localization.fileSavedInPath
|
showToast(localization.fileSavedInPath
|
||||||
.replaceFirst(':path', directory.path));
|
.replaceFirst(':path', directory));
|
||||||
} else {
|
} else {
|
||||||
await Share.shareXFiles([XFile(filePath)]);
|
await Share.shareXFiles([XFile(filePath)]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import 'package:http/http.dart' as http;
|
||||||
import 'package:http/http.dart';
|
import 'package:http/http.dart';
|
||||||
import 'package:invoiceninja_flutter/main_app.dart';
|
import 'package:invoiceninja_flutter/main_app.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/dialogs/error_dialog.dart';
|
import 'package:invoiceninja_flutter/ui/app/dialogs/error_dialog.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:invoiceninja_flutter/utils/files.dart';
|
||||||
import 'package:printing/printing.dart';
|
import 'package:printing/printing.dart';
|
||||||
import 'package:share_plus/share_plus.dart';
|
import 'package:share_plus/share_plus.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
@ -269,16 +269,15 @@ class _InvoicePdfViewState extends State<InvoicePdfView> {
|
||||||
WebUtils.downloadBinaryFile(
|
WebUtils.downloadBinaryFile(
|
||||||
fileName, _response!.bodyBytes);
|
fileName, _response!.bodyBytes);
|
||||||
} else {
|
} else {
|
||||||
final directory = await (isDesktopOS()
|
final directory =
|
||||||
? getDownloadsDirectory()
|
await getAppDownloadDirectory();
|
||||||
: getApplicationDocumentsDirectory());
|
|
||||||
|
|
||||||
if (directory == null) {
|
if (directory == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String filePath =
|
String filePath =
|
||||||
'${directory.path}${file.Platform.pathSeparator}$fileName';
|
'$directory${file.Platform.pathSeparator}$fileName';
|
||||||
|
|
||||||
if (file.File(filePath).existsSync()) {
|
if (file.File(filePath).existsSync()) {
|
||||||
final timestamp =
|
final timestamp =
|
||||||
|
|
@ -293,7 +292,7 @@ class _InvoicePdfViewState extends State<InvoicePdfView> {
|
||||||
|
|
||||||
if (isDesktopOS()) {
|
if (isDesktopOS()) {
|
||||||
showToast(localization.fileSavedInPath
|
showToast(localization.fileSavedInPath
|
||||||
.replaceFirst(':path', directory.path));
|
.replaceFirst(':path', directory));
|
||||||
} else {
|
} else {
|
||||||
await Share.shareXFiles([XFile(filePath)]);
|
await Share.shareXFiles([XFile(filePath)]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,9 @@ import 'package:invoiceninja_flutter/ui/reports/recurring_expense_report.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/reports/recurring_invoice_report.dart';
|
import 'package:invoiceninja_flutter/ui/reports/recurring_invoice_report.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/reports/transaction_report.dart';
|
import 'package:invoiceninja_flutter/ui/reports/transaction_report.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/reports/vendor_report.dart';
|
import 'package:invoiceninja_flutter/ui/reports/vendor_report.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/files.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
||||||
import 'package:memoize/memoize.dart';
|
import 'package:memoize/memoize.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
|
||||||
import 'package:redux/redux.dart';
|
import 'package:redux/redux.dart';
|
||||||
|
|
||||||
// Project imports:
|
// Project imports:
|
||||||
|
|
@ -511,22 +511,19 @@ class ReportsScreenVM {
|
||||||
if (kIsWeb) {
|
if (kIsWeb) {
|
||||||
WebUtils.downloadTextFile(filename, csvData);
|
WebUtils.downloadTextFile(filename, csvData);
|
||||||
} else {
|
} else {
|
||||||
final directory = await (isDesktopOS()
|
final directory = await getAppDownloadDirectory();
|
||||||
? getDownloadsDirectory()
|
|
||||||
: getApplicationDocumentsDirectory());
|
|
||||||
|
|
||||||
if (directory == null) {
|
if (directory == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final filePath =
|
final filePath = directory + file.Platform.pathSeparator + filename;
|
||||||
directory.path + file.Platform.pathSeparator + filename;
|
|
||||||
final csvFile = file.File(filePath);
|
final csvFile = file.File(filePath);
|
||||||
await csvFile.writeAsString(csvData);
|
await csvFile.writeAsString(csvData);
|
||||||
|
|
||||||
if (isDesktopOS()) {
|
if (isDesktopOS()) {
|
||||||
showToast(localization!.fileSavedInPath
|
showToast(localization!.fileSavedInPath
|
||||||
.replaceFirst(':path', directory.path));
|
.replaceFirst(':path', directory));
|
||||||
} else {
|
} else {
|
||||||
await Share.shareXFiles([XFile(filePath)]);
|
await Share.shareXFiles([XFile(filePath)]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,10 @@ import 'package:flutter/foundation.dart';
|
||||||
// Package imports:
|
// Package imports:
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:http/http.dart';
|
import 'package:http/http.dart';
|
||||||
|
import 'package:invoiceninja_flutter/main_app.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/dialogs.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:permission_handler/permission_handler.dart';
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
|
|
||||||
// Project imports:
|
// Project imports:
|
||||||
|
|
@ -77,3 +81,24 @@ Future<List<MultipartFile>?> _pickFiles({
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<String?> getAppDownloadDirectory() async {
|
||||||
|
final directory = await (isDesktopOS()
|
||||||
|
? getDownloadsDirectory()
|
||||||
|
: getApplicationDocumentsDirectory());
|
||||||
|
|
||||||
|
if (directory == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Directory(directory.path).existsSync()) {
|
||||||
|
showErrorDialog(
|
||||||
|
message: AppLocalization.of(navigatorKey.currentContext!)!
|
||||||
|
.directoryDoesNotExist
|
||||||
|
.replaceFirst(':value', directory.path));
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return directory.path;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
||||||
static final Map<String, Map<String, String>> _localizedValues = {
|
static final Map<String, Map<String, String>> _localizedValues = {
|
||||||
'en': {
|
'en': {
|
||||||
// STARTER: lang key - do not remove comment
|
// STARTER: lang key - do not remove comment
|
||||||
|
'directory_does_not_exist':
|
||||||
|
'The download directory does not exist :value',
|
||||||
'user_logged_in_notification': 'User Logged in Notification',
|
'user_logged_in_notification': 'User Logged in Notification',
|
||||||
'user_logged_in_notification_help':
|
'user_logged_in_notification_help':
|
||||||
'Send an email when logging in from a new location',
|
'Send an email when logging in from a new location',
|
||||||
|
|
@ -109898,6 +109900,10 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
||||||
_localizedValues[localeCode]!['user_logged_in_notification_help'] ??
|
_localizedValues[localeCode]!['user_logged_in_notification_help'] ??
|
||||||
_localizedValues['en']!['user_logged_in_notification_help']!;
|
_localizedValues['en']!['user_logged_in_notification_help']!;
|
||||||
|
|
||||||
|
String get directoryDoesNotExist =>
|
||||||
|
_localizedValues[localeCode]!['directory_does_not_exist'] ??
|
||||||
|
_localizedValues['en']!['directory_does_not_exist']!;
|
||||||
|
|
||||||
// STARTER: lang field - do not remove comment
|
// STARTER: lang field - do not remove comment
|
||||||
|
|
||||||
String lookup(String? key) {
|
String lookup(String? key) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue