Skip to content

Commit

Permalink
Merge pull request #136 from astubenbord/feature/119-sharing-pdf-missing
Browse files Browse the repository at this point in the history
Feature/119 sharing pdf missing
  • Loading branch information
astubenbord authored Mar 6, 2023
2 parents 527fb16 + c7da398 commit e3e2ce1
Show file tree
Hide file tree
Showing 37 changed files with 1,005 additions and 308 deletions.
Binary file added android/app/src/main/res/drawable/downloading.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions assets/images/bmc-logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions lib/core/bloc/connectivity_cubit.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:paperless_mobile/core/service/connectivity_status_service.dart';

Expand Down Expand Up @@ -45,6 +46,13 @@ class ConnectivityCubit extends Cubit<ConnectivityState> {
}
}

extension ConnectivityFromContext on BuildContext {
bool get watchInternetConnection =>
watch<ConnectivityCubit>().state.isConnected;
bool get readInternetConnection =>
read<ConnectivityCubit>().state.isConnected;
}

enum ConnectivityState {
connected,
notConnected,
Expand Down
16 changes: 16 additions & 0 deletions lib/features/app_drawer/view/app_drawer.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:paperless_mobile/constants.dart';
import 'package:paperless_mobile/core/widgets/paperless_logo.dart';
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
Expand Down Expand Up @@ -45,6 +46,21 @@ class AppDrawer extends StatelessWidget {
'https://github.com/astubenbord/paperless-mobile/issues/new');
},
),
ListTile(
dense: true,
leading: Padding(
padding: const EdgeInsets.only(left: 3),
child: SvgPicture.asset(
'assets/images/bmc-logo.svg',
width: 24,
height: 24,
),
),
title: Text(S.of(context)!.donateCoffee),
onTap: () {
launchUrlString("https://www.buymeacoffee.com/astubenbord");
},
),
ListTile(
dense: true,
leading: const Icon(Icons.settings_outlined),
Expand Down
145 changes: 121 additions & 24 deletions lib/features/document_details/cubit/document_details_cubit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ import 'dart:io';

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:open_filex/open_filex.dart';
import 'package:paperless_api/paperless_api.dart';
import 'package:paperless_mobile/core/notifier/document_changed_notifier.dart';
import 'package:paperless_mobile/core/service/file_description.dart';
import 'package:paperless_mobile/core/service/file_service.dart';
import 'package:paperless_mobile/features/notifications/services/local_notification_service.dart';
import 'package:path_provider/path_provider.dart';
import 'package:share_plus/share_plus.dart';

Expand All @@ -15,15 +18,18 @@ part 'document_details_state.dart';
class DocumentDetailsCubit extends Cubit<DocumentDetailsState> {
final PaperlessDocumentsApi _api;
final DocumentChangedNotifier _notifier;
final LocalNotificationService _notificationService;

final List<StreamSubscription> _subscriptions = [];
DocumentDetailsCubit(
this._api,
this._notifier, {
this._notifier,
this._notificationService, {
required DocumentModel initialDocument,
}) : super(DocumentDetailsState(document: initialDocument)) {
_notifier.subscribe(this, onUpdated: replace);
loadSuggestions();
loadMetaData();
}

Future<void> delete(DocumentModel document) async {
Expand All @@ -36,6 +42,11 @@ class DocumentDetailsCubit extends Cubit<DocumentDetailsState> {
emit(state.copyWith(suggestions: suggestions));
}

Future<void> loadMetaData() async {
final metaData = await _api.getMetaData(state.document);
emit(state.copyWith(metaData: metaData));
}

Future<void> loadFullContent() async {
final doc = await _api.find(state.document.id);
if (doc == null) {
Expand All @@ -47,43 +58,120 @@ class DocumentDetailsCubit extends Cubit<DocumentDetailsState> {
));
}

Future<void> assignAsn(DocumentModel document) async {
if (document.archiveSerialNumber == null) {
final int asn = await _api.findNextAsn();
final updatedDocument =
await _api.update(document.copyWith(archiveSerialNumber: asn));
Future<void> assignAsn(
DocumentModel document, {
int? asn,
bool autoAssign = false,
}) async {
if (!autoAssign) {
final updatedDocument = await _api.update(
document.copyWith(archiveSerialNumber: () => asn),
);
_notifier.notifyUpdated(updatedDocument);
} else {
final int autoAsn = await _api.findNextAsn();
final updatedDocument = await _api
.update(document.copyWith(archiveSerialNumber: () => autoAsn));
_notifier.notifyUpdated(updatedDocument);
}
}

Future<ResultType> openDocumentInSystemViewer() async {
final cacheDir = await FileService.temporaryDirectory;
await FileService.clearDirectoryContent(PaperlessDirectoryType.temporary);
if (state.metaData == null) {
await loadMetaData();
}
final desc = FileDescription.fromPath(
state.metaData!.mediaFilename.replaceAll("/", " "));

final metaData = await _api.getMetaData(state.document);
final bytes = await _api.download(state.document);

final file = File('${cacheDir.path}/${metaData.mediaFilename}')
..createSync(recursive: true)
..writeAsBytesSync(bytes);
final fileName = "${desc.filename}.pdf";
final file = File("${cacheDir.path}/$fileName");

return OpenFilex.open(file.path, type: "application/pdf").then(
(value) => value.type,
);
if (!file.existsSync()) {
file.createSync();
await _api.downloadToFile(
state.document,
file.path,
);
}
return OpenFilex.open(
file.path,
type: "application/pdf",
).then((value) => value.type);
}

void replace(DocumentModel document) {
emit(state.copyWith(document: document));
}

Future<void> shareDocument() async {
final documentBytes = await _api.download(state.document);
final dir = await getTemporaryDirectory();
final String path = "${dir.path}/${state.document.originalFileName}";
await File(path).writeAsBytes(documentBytes);
Future<void> downloadDocument({
bool downloadOriginal = false,
required String locale,
}) async {
if (state.metaData == null) {
await loadMetaData();
}
String filePath = _buildDownloadFilePath(
downloadOriginal,
await FileService.downloadsDirectory,
);
final desc = FileDescription.fromPath(
state.metaData!.mediaFilename
.replaceAll("/", " "), // Flatten directory structure
);
if (!File(filePath).existsSync()) {
File(filePath).createSync();
} else {
return _notificationService.notifyFileDownload(
document: state.document,
filename: "${desc.filename}.${desc.extension}",
filePath: filePath,
finished: true,
locale: locale,
);
}

await _notificationService.notifyFileDownload(
document: state.document,
filename: "${desc.filename}.${desc.extension}",
filePath: filePath,
finished: false,
locale: locale,
);

await _api.downloadToFile(
state.document,
filePath,
original: downloadOriginal,
);
await _notificationService.notifyFileDownload(
document: state.document,
filename: "${desc.filename}.${desc.extension}",
filePath: filePath,
finished: true,
locale: locale,
);
debugPrint("Downloaded file to $filePath");
}

Future<void> shareDocument({bool shareOriginal = false}) async {
if (state.metaData == null) {
await loadMetaData();
}
String filePath = _buildDownloadFilePath(
shareOriginal,
await FileService.temporaryDirectory,
);
await _api.downloadToFile(
state.document,
filePath,
original: shareOriginal,
);
Share.shareXFiles(
[
XFile(
path,
filePath,
name: state.document.originalFileName,
mimeType: "application/pdf",
lastModified: state.document.modified,
Expand All @@ -93,12 +181,21 @@ class DocumentDetailsCubit extends Cubit<DocumentDetailsState> {
);
}

String _buildDownloadFilePath(bool original, Directory dir) {
final description = FileDescription.fromPath(
state.metaData!.mediaFilename
.replaceAll("/", " "), // Flatten directory structure
);
final extension = original ? description.extension : 'pdf';
return "${dir.path}/${description.filename}.$extension";
}

@override
Future<void> close() {
Future<void> close() async {
for (final element in _subscriptions) {
element.cancel();
await element.cancel();
}
_notifier.unsubscribe(this);
return super.close();
await super.close();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ part of 'document_details_cubit.dart';

class DocumentDetailsState with EquatableMixin {
final DocumentModel document;
final DocumentMetaData? metaData;
final bool isFullContentLoaded;
final String? fullContent;
final FieldSuggestions suggestions;

const DocumentDetailsState({
required this.document,
this.metaData,
this.suggestions = const FieldSuggestions(),
this.isFullContentLoaded = false,
this.fullContent,
Expand All @@ -19,19 +21,22 @@ class DocumentDetailsState with EquatableMixin {
suggestions,
isFullContentLoaded,
fullContent,
metaData,
];

DocumentDetailsState copyWith({
DocumentModel? document,
FieldSuggestions? suggestions,
bool? isFullContentLoaded,
String? fullContent,
DocumentMetaData? metaData,
}) {
return DocumentDetailsState(
document: document ?? this.document,
suggestions: suggestions ?? this.suggestions,
isFullContentLoaded: isFullContentLoaded ?? this.isFullContentLoaded,
fullContent: fullContent ?? this.fullContent,
metaData: metaData ?? this.metaData,
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import 'package:flutter/material.dart';
import 'package:paperless_mobile/features/settings/view/widgets/radio_settings_dialog.dart';
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';

class SelectFileTypeDialog extends StatelessWidget {
const SelectFileTypeDialog({super.key});

@override
Widget build(BuildContext context) {
return RadioSettingsDialog(
titleText: S.of(context)!.chooseFiletype,
options: [
RadioOption(
value: true,
label: S.of(context)!.original,
),
RadioOption(
value: false,
label: S.of(context)!.archivedPdf,
),
],
initialValue: false,
);
}
}
Loading

0 comments on commit e3e2ce1

Please sign in to comment.