157 lines
4.4 KiB
Dart
157 lines
4.4 KiB
Dart
// Dart imports:
|
|
import 'dart:io';
|
|
import 'dart:io' as file;
|
|
|
|
// Flutter imports:
|
|
import 'package:device_info_plus/device_info_plus.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
|
|
// Package imports:
|
|
import 'package:file_picker/file_picker.dart';
|
|
import 'package:flutter_redux/flutter_redux.dart';
|
|
import 'package:flutter_styled_toast/flutter_styled_toast.dart';
|
|
import 'package:http/http.dart';
|
|
import 'package:invoiceninja_flutter/main_app.dart';
|
|
import 'package:invoiceninja_flutter/redux/app/app_state.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';
|
|
|
|
// Project imports:
|
|
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
|
|
|
// ignore: unused_import
|
|
import 'package:invoiceninja_flutter/utils/web_stub.dart'
|
|
if (dart.library.html) 'package:invoiceninja_flutter/utils/web.dart';
|
|
import 'package:share_plus/share_plus.dart';
|
|
|
|
Future<List<MultipartFile>?> pickFiles({
|
|
String? fileIndex,
|
|
FileType? fileType,
|
|
List<String>? allowedExtensions,
|
|
bool allowMultiple = true,
|
|
}) async {
|
|
if (kIsWeb || isDesktopOS()) {
|
|
return _pickFiles(
|
|
fileIndex: fileIndex,
|
|
fileType: fileType,
|
|
allowedExtensions: allowedExtensions,
|
|
allowMultiple: allowMultiple,
|
|
);
|
|
} else {
|
|
final androidInfo = await DeviceInfoPlugin().androidInfo;
|
|
PermissionStatus status;
|
|
|
|
if (Platform.isIOS && fileType == FileType.image) {
|
|
status = await Permission.photos.request();
|
|
} else if (Platform.isAndroid && androidInfo.version.sdkInt >= 33) {
|
|
status = await Permission.photos.request();
|
|
} else {
|
|
status = await Permission.storage.request();
|
|
}
|
|
|
|
if (status == PermissionStatus.granted) {
|
|
return _pickFiles(
|
|
fileIndex: fileIndex,
|
|
fileType: fileType,
|
|
allowedExtensions: allowedExtensions,
|
|
allowMultiple: allowMultiple,
|
|
);
|
|
} else {
|
|
openAppSettings();
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
|
|
Future<List<MultipartFile>?> _pickFiles({
|
|
String? fileIndex,
|
|
FileType? fileType,
|
|
List<String>? allowedExtensions,
|
|
required bool allowMultiple,
|
|
}) async {
|
|
final result = await FilePicker.platform.pickFiles(
|
|
type: fileType ?? FileType.custom,
|
|
allowedExtensions:
|
|
fileType == FileType.image ? [] : allowedExtensions ?? [],
|
|
allowCompression: true,
|
|
withData: true,
|
|
allowMultiple: allowMultiple,
|
|
);
|
|
|
|
if (result != null && result.files.isNotEmpty) {
|
|
final multipartFiles = <MultipartFile>[];
|
|
for (var index = 0; index < result.files.length; index++) {
|
|
final file = result.files[index];
|
|
multipartFiles.add(MultipartFile.fromBytes(
|
|
allowMultiple ? 'documents[$index]' : fileIndex!, file.bytes!,
|
|
filename: file.name));
|
|
}
|
|
|
|
return multipartFiles;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
void saveDownloadedFile(Uint8List data, String fileName) async {
|
|
if (kIsWeb) {
|
|
WebUtils.downloadBinaryFile(fileName, data);
|
|
} else {
|
|
final directory = await getAppDownloadDirectory();
|
|
if (directory != null) {
|
|
String filePath = '$directory/${file.Platform.pathSeparator}$fileName';
|
|
|
|
if (file.File(filePath).existsSync()) {
|
|
final extension = fileName.split('.').last;
|
|
final timestamp = DateTime.now().millisecondsSinceEpoch;
|
|
filePath =
|
|
filePath.replaceFirst('.$extension', '_$timestamp.$extension');
|
|
}
|
|
|
|
await File(filePath).writeAsBytes(data);
|
|
|
|
if (isDesktopOS()) {
|
|
showToast(AppLocalization.of(navigatorKey.currentContext!)!
|
|
.fileSavedInPath
|
|
.replaceFirst(':path', directory));
|
|
} else {
|
|
await Share.shareXFiles([XFile(filePath)]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Future<String?> getAppDownloadDirectory() async {
|
|
var path = '';
|
|
|
|
final store = StoreProvider.of<AppState>(navigatorKey.currentContext!);
|
|
final state = store.state;
|
|
|
|
if (state.prefState.donwloadsFolder.isNotEmpty) {
|
|
path = state.prefState.donwloadsFolder;
|
|
} else {
|
|
final directory = await (isDesktopOS()
|
|
? getDownloadsDirectory()
|
|
: getApplicationDocumentsDirectory());
|
|
|
|
if (directory == null) {
|
|
return null;
|
|
}
|
|
|
|
path = directory.path;
|
|
}
|
|
|
|
if (!Directory(path).existsSync()) {
|
|
showErrorDialog(
|
|
message: AppLocalization.of(navigatorKey.currentContext!)!
|
|
.downloadsFolderDoesNotExist
|
|
.replaceFirst(':value', path));
|
|
|
|
return null;
|
|
}
|
|
|
|
return path;
|
|
}
|