mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2025-12-10 10:08:02 -06:00
Enabled download functionality for android and added share functionality for document pdfs
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.5.31'
|
ext.kotlin_version = '1.7.0'
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
|||||||
@@ -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;
|
||||||
getIt<DocumentRepository>().download(document).then((bytes) async {
|
|
||||||
//FIXME: logic currently flawed, some error somewhere but cannot look into directory...
|
|
||||||
final dir = await getApplicationDocumentsDirectory();
|
|
||||||
final dirPath = dir.path + "/files/";
|
|
||||||
var filePath = dirPath + document.originalFileName;
|
|
||||||
|
|
||||||
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();
|
setState(() => _isDownloadPending = true);
|
||||||
|
getIt<DocumentRepository>().download(document).then((bytes) async {
|
||||||
|
final Directory dir =
|
||||||
|
(await getExternalStorageDirectories(type: StorageDirectory.downloads))!.first;
|
||||||
|
String filePath = "${dir.path}/${document.originalFileName}";
|
||||||
|
//TODO: Add replacement mechanism here (ask user if file should be replaced if exists)
|
||||||
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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
33
pubspec.lock
33
pubspec.lock
@@ -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:
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
Reference in New Issue
Block a user