Enabled download functionality for android and added share functionality for document pdfs

This commit is contained in:
Anton Stubenbord
2022-11-02 00:32:37 +01:00
parent 2a1b90cc42
commit dcf3fbdc4b
6 changed files with 74 additions and 30 deletions

View File

@@ -26,7 +26,7 @@ apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android { android {
compileSdkVersion 31 compileSdkVersion 33
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8

View File

@@ -1,5 +1,5 @@
buildscript { buildscript {
ext.kotlin_version = '1.5.31' ext.kotlin_version = '1.7.0'
repositories { repositories {
google() google()
mavenCentral() mavenCentral()

View File

@@ -1,6 +1,8 @@
import 'dart:developer' as dev;
import 'dart:io'; import 'dart:io';
import 'dart:math'; import 'dart:math';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_paperless_mobile/core/bloc/label_bloc_provider.dart'; import 'package:flutter_paperless_mobile/core/bloc/label_bloc_provider.dart';
@@ -26,6 +28,7 @@ import 'package:flutter_paperless_mobile/generated/l10n.dart';
import 'package:flutter_paperless_mobile/util.dart'; import 'package:flutter_paperless_mobile/util.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:share_plus/share_plus.dart';
class DocumentDetailsPage extends StatefulWidget { class DocumentDetailsPage extends StatefulWidget {
final int documentId; final int documentId;
@@ -73,12 +76,16 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
).padded(const EdgeInsets.symmetric(horizontal: 8.0)), ).padded(const EdgeInsets.symmetric(horizontal: 8.0)),
IconButton( IconButton(
icon: const Icon(Icons.download), icon: const Icon(Icons.download),
onPressed: null, //() => _onDownload(document), //TODO: FIX onPressed: Platform.isAndroid ? () => _onDownload(document) : null,
), ),
IconButton( IconButton(
icon: const Icon(Icons.open_in_new), icon: const Icon(Icons.open_in_new),
onPressed: () => _onOpen(document), onPressed: () => _onOpen(document),
).padded(const EdgeInsets.symmetric(horizontal: 8.0)), ).padded(const EdgeInsets.symmetric(horizontal: 8.0)),
IconButton(
icon: const Icon(Icons.share),
onPressed: () => _onShare(document),
),
], ],
), ),
), ),
@@ -313,31 +320,43 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
} }
Future<void> _onDownload(DocumentModel document) async { Future<void> _onDownload(DocumentModel document) async {
setState(() { if (!Platform.isAndroid) {
_isDownloadPending = true; showSnackBar(context, "This feature is currently only supported on Android!");
}); return;
}
setState(() => _isDownloadPending = true);
getIt<DocumentRepository>().download(document).then((bytes) async { getIt<DocumentRepository>().download(document).then((bytes) async {
//FIXME: logic currently flawed, some error somewhere but cannot look into directory... final Directory dir =
final dir = await getApplicationDocumentsDirectory(); (await getExternalStorageDirectories(type: StorageDirectory.downloads))!.first;
final dirPath = dir.path + "/files/"; String filePath = "${dir.path}/${document.originalFileName}";
var filePath = dirPath + document.originalFileName; //TODO: Add replacement mechanism here (ask user if file should be replaced if exists)
if (File(filePath).existsSync()) {
final count = dir
.listSync()
.where((entity) => (entity.path.contains(document.originalFileName)))
.fold<int>(0, (previous, element) => previous + 1);
final extSeperationIdx = filePath.lastIndexOf(".");
filePath =
filePath.replaceRange(extSeperationIdx, extSeperationIdx + 1, " (${count + 1}).");
}
Directory(dirPath).createSync();
await File(filePath).writeAsBytes(bytes); await File(filePath).writeAsBytes(bytes);
_isDownloadPending = false; setState(() => _isDownloadPending = false);
showSnackBar(context, "Document successfully downloaded to $filePath"); //TODO: INTL dev.log("File downloaded to $filePath");
}); });
} }
///
/// Downloads file to temporary directory, from which it can then be shared.
///
Future<void> _onShare(DocumentModel document) async {
Uint8List documentBytes = await getIt<DocumentRepository>().download(document);
final dir = await getTemporaryDirectory();
final String path = "${dir.path}/${document.originalFileName}";
await File(path).writeAsBytes(documentBytes);
Share.shareXFiles(
[
XFile(
path,
name: document.originalFileName,
mimeType: "application/pdf",
lastModified: document.modified,
)
],
subject: document.title,
);
}
Future<void> _onDelete(DocumentModel document) async { Future<void> _onDelete(DocumentModel document) async {
showDialog( showDialog(
context: context, context: context,

View File

@@ -20,6 +20,7 @@ import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:intl/intl_standalone.dart'; import 'package:intl/intl_standalone.dart';
import 'package:package_info_plus/package_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart';
import 'package:path_provider/path_provider.dart';
void main() async { void main() async {
final widgetsBinding = WidgetsFlutterBinding.ensureInitialized(); final widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
@@ -30,6 +31,8 @@ void main() async {
HttpOverrides.global = X509HttpOverrides(); HttpOverrides.global = X509HttpOverrides();
configureDependencies(); configureDependencies();
// Remove temporarily downloaded files.
(await getTemporaryDirectory()).deleteSync(recursive: true);
kPackageInfo = await PackageInfo.fromPlatform(); kPackageInfo = await PackageInfo.fromPlatform();
// Load application settings and stored authentication data // Load application settings and stored authentication data

View File

@@ -246,6 +246,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.5.0" version: "1.5.0"
cross_file:
dependency: transitive
description:
name: cross_file
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.3+2"
crypto: crypto:
dependency: transitive dependency: transitive
description: description:
@@ -898,7 +905,7 @@ packages:
name: package_info_plus_windows name: package_info_plus_windows
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.0" version: "2.1.0"
path: path:
dependency: transitive dependency: transitive
description: description:
@@ -926,7 +933,7 @@ packages:
name: path_provider name: path_provider
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.10" version: "2.0.11"
path_provider_android: path_provider_android:
dependency: transitive dependency: transitive
description: description:
@@ -968,7 +975,7 @@ packages:
name: path_provider_windows name: path_provider_windows
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.2" version: "2.1.3"
pdf: pdf:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -1109,6 +1116,20 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.27.4" version: "0.27.4"
share_plus:
dependency: "direct main"
description:
name: share_plus
url: "https://pub.dartlang.org"
source: hosted
version: "6.2.0"
share_plus_platform_interface:
dependency: transitive
description:
name: share_plus_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "3.2.0"
shared_preferences: shared_preferences:
dependency: transitive dependency: transitive
description: description:
@@ -1407,14 +1428,14 @@ packages:
name: url_launcher_platform_interface name: url_launcher_platform_interface
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.5" version: "2.1.1"
url_launcher_web: url_launcher_web:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_web name: url_launcher_web
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.11" version: "2.0.13"
url_launcher_windows: url_launcher_windows:
dependency: transitive dependency: transitive
description: description:
@@ -1477,7 +1498,7 @@ packages:
name: win32 name: win32
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.7.0" version: "3.0.1"
xdg_directories: xdg_directories:
dependency: transitive dependency: transitive
description: description:

View File

@@ -17,7 +17,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at # Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.0.1 version: 1.0.2
environment: environment:
sdk: ">=2.17.0 <3.0.0" sdk: ">=2.17.0 <3.0.0"
@@ -72,6 +72,7 @@ dependencies:
connectivity_plus: ^2.3.9 connectivity_plus: ^2.3.9
flutter_native_splash: ^2.2.11 flutter_native_splash: ^2.2.11
share_plus: ^6.2.0
dev_dependencies: dev_dependencies:
integration_test: integration_test: