mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2025-12-10 22:07:55 -06:00
Improved error handling, added multithreading for fromJson calls, made receive sharing intent more robust
This commit is contained in:
@@ -22,19 +22,22 @@ class DocumentScannerCubit extends Cubit<List<File>> {
|
||||
scans.removeAt(fileIndex);
|
||||
emit(scans);
|
||||
} catch (_) {
|
||||
addError(const ErrorMessage(ErrorCode.scanRemoveFailed));
|
||||
throw const ErrorMessage(ErrorCode.scanRemoveFailed);
|
||||
}
|
||||
}
|
||||
|
||||
void reset() {
|
||||
for (final doc in state) {
|
||||
doc.deleteSync();
|
||||
if (kDebugMode) {
|
||||
log('[ScannerCubit]: Removed ${doc.path}');
|
||||
try {
|
||||
for (final doc in state) {
|
||||
doc.deleteSync();
|
||||
if (kDebugMode) {
|
||||
log('[ScannerCubit]: Removed ${doc.path}');
|
||||
}
|
||||
}
|
||||
imageCache.clear();
|
||||
emit(initialState);
|
||||
} catch (_) {
|
||||
throw const ErrorMessage(ErrorCode.scanRemoveFailed);
|
||||
}
|
||||
|
||||
imageCache.clear();
|
||||
emit(initialState);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,51 +185,32 @@ class _DocumentUploadPageState extends State<DocumentUploadPage> {
|
||||
}
|
||||
|
||||
void _onSubmit() async {
|
||||
_formKey.currentState?.save();
|
||||
if (_formKey.currentState?.validate() ?? false) {
|
||||
if (_formKey.currentState?.saveAndValidate() ?? false) {
|
||||
try {
|
||||
setState(() {
|
||||
_isUploadLoading = true;
|
||||
});
|
||||
setState(() => _isUploadLoading = true);
|
||||
|
||||
final fv = _formKey.currentState!.value;
|
||||
|
||||
final createdAt = fv[DocumentModel.createdKey] as DateTime?;
|
||||
final title = fv[DocumentModel.titleKey] as String;
|
||||
final docType = fv[DocumentModel.documentTypeKey] as IdQueryParameter;
|
||||
final tags = fv[DocumentModel.tagsKey] as TagsQuery;
|
||||
final correspondent =
|
||||
fv[DocumentModel.correspondentKey] as IdQueryParameter;
|
||||
|
||||
await BlocProvider.of<DocumentsCubit>(context).addDocument(
|
||||
widget.fileBytes,
|
||||
_formKey.currentState?.value[fkFileName],
|
||||
onConsumptionFinished: (document) {
|
||||
ScaffoldMessenger.of(rootScaffoldKey.currentContext!).showSnackBar(
|
||||
SnackBar(
|
||||
action: SnackBarAction(
|
||||
onPressed: () {
|
||||
getIt<DocumentsCubit>().reloadDocuments();
|
||||
},
|
||||
label: S
|
||||
.of(context)
|
||||
.documentUploadProcessingSuccessfulReloadActionText,
|
||||
),
|
||||
content:
|
||||
Text(S.of(context).documentUploadProcessingSuccessfulText),
|
||||
),
|
||||
);
|
||||
},
|
||||
title: _formKey.currentState?.value[DocumentModel.titleKey],
|
||||
documentType: (_formKey.currentState
|
||||
?.value[DocumentModel.documentTypeKey] as IdQueryParameter)
|
||||
.id,
|
||||
correspondent: (_formKey.currentState
|
||||
?.value[DocumentModel.correspondentKey] as IdQueryParameter)
|
||||
.id,
|
||||
tags:
|
||||
(_formKey.currentState?.value[DocumentModel.tagsKey] as TagsQuery)
|
||||
.ids,
|
||||
createdAt: (_formKey.currentState?.value[DocumentModel.createdKey]
|
||||
as DateTime?),
|
||||
propagateEventOnError: false,
|
||||
onConsumptionFinished: _onConsumptionFinished,
|
||||
title: title,
|
||||
documentType: docType.id,
|
||||
correspondent: correspondent.id,
|
||||
tags: tags.ids,
|
||||
createdAt: createdAt,
|
||||
);
|
||||
setState(() {
|
||||
_isUploadLoading = false;
|
||||
});
|
||||
getIt<DocumentScannerCubit>().reset();
|
||||
Navigator.pop(context);
|
||||
getIt<DocumentScannerCubit>().reset(); //TODO: Access via provider
|
||||
showSnackBar(context, S.of(context).documentUploadSuccessText);
|
||||
Navigator.pop(context);
|
||||
widget.afterUpload?.call();
|
||||
} on ErrorMessage catch (error) {
|
||||
showError(context, error);
|
||||
@@ -239,9 +220,28 @@ class _DocumentUploadPageState extends State<DocumentUploadPage> {
|
||||
showSnackBar(context, other.toString());
|
||||
} finally {
|
||||
setState(() {
|
||||
_isUploadLoading = true;
|
||||
_isUploadLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _onConsumptionFinished(document) {
|
||||
ScaffoldMessenger.of(rootScaffoldKey.currentContext!).showSnackBar(
|
||||
SnackBar(
|
||||
action: SnackBarAction(
|
||||
onPressed: () async {
|
||||
try {
|
||||
getIt<DocumentsCubit>().reloadDocuments();
|
||||
} on ErrorMessage catch (error) {
|
||||
showError(context, error);
|
||||
}
|
||||
},
|
||||
label:
|
||||
S.of(context).documentUploadProcessingSuccessfulReloadActionText,
|
||||
),
|
||||
content: Text(S.of(context).documentUploadProcessingSuccessfulText),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@ import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:mime/mime.dart';
|
||||
import 'package:paperless_mobile/core/bloc/global_error_cubit.dart';
|
||||
import 'package:paperless_mobile/core/bloc/label_bloc_provider.dart';
|
||||
import 'package:paperless_mobile/core/global/constants.dart';
|
||||
import 'package:paperless_mobile/core/model/error_message.dart';
|
||||
import 'package:paperless_mobile/core/service/file_service.dart';
|
||||
import 'package:paperless_mobile/di_initializer.dart';
|
||||
@@ -19,6 +19,7 @@ import 'package:paperless_mobile/features/scan/bloc/document_scanner_cubit.dart'
|
||||
import 'package:paperless_mobile/features/scan/view/document_upload_page.dart';
|
||||
import 'package:paperless_mobile/features/scan/view/widgets/grid_image_item_widget.dart';
|
||||
import 'package:paperless_mobile/generated/l10n.dart';
|
||||
import 'package:paperless_mobile/util.dart';
|
||||
import 'package:pdf/pdf.dart';
|
||||
import 'package:pdf/widgets.dart' as pw;
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
@@ -32,15 +33,6 @@ class ScannerPage extends StatefulWidget {
|
||||
|
||||
class _ScannerPageState extends State<ScannerPage>
|
||||
with SingleTickerProviderStateMixin {
|
||||
static const _supportedExtensions = [
|
||||
'pdf',
|
||||
'png',
|
||||
'tiff',
|
||||
'gif',
|
||||
'jpg',
|
||||
'jpeg'
|
||||
];
|
||||
|
||||
late final AnimationController _fabPulsingController;
|
||||
late final Animation _animation;
|
||||
|
||||
@@ -205,8 +197,14 @@ class _ScannerPageState extends State<ScannerPage>
|
||||
itemBuilder: (context, index) {
|
||||
return GridImageItemWidget(
|
||||
file: scans[index],
|
||||
onDelete: () => BlocProvider.of<DocumentScannerCubit>(context)
|
||||
.removeScan(index),
|
||||
onDelete: () async {
|
||||
try {
|
||||
BlocProvider.of<DocumentScannerCubit>(context)
|
||||
.removeScan(index);
|
||||
} on ErrorMessage catch (error) {
|
||||
showError(context, error);
|
||||
}
|
||||
},
|
||||
index: index,
|
||||
totalNumberOfFiles: scans.length,
|
||||
);
|
||||
@@ -214,7 +212,11 @@ class _ScannerPageState extends State<ScannerPage>
|
||||
}
|
||||
|
||||
void _reset(BuildContext context) {
|
||||
BlocProvider.of<DocumentScannerCubit>(context).reset();
|
||||
try {
|
||||
BlocProvider.of<DocumentScannerCubit>(context).reset();
|
||||
} on ErrorMessage catch (error) {
|
||||
showError(context, error);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _requestCameraPermissions() async {
|
||||
@@ -227,15 +229,14 @@ class _ScannerPageState extends State<ScannerPage>
|
||||
void _onUploadFromFilesystem() async {
|
||||
FilePickerResult? result = await FilePicker.platform.pickFiles(
|
||||
type: FileType.custom,
|
||||
allowedExtensions: _supportedExtensions,
|
||||
allowedExtensions: supportedFileExtensions,
|
||||
withData: true,
|
||||
);
|
||||
if (result?.files.single.path != null) {
|
||||
File file = File(result!.files.single.path!);
|
||||
if (!_supportedExtensions.contains(file.path.split('.').last)) {
|
||||
return getIt<GlobalErrorCubit>().add(
|
||||
const ErrorMessage(ErrorCode.unsupportedFileFormat),
|
||||
);
|
||||
if (!supportedFileExtensions.contains(file.path.split('.').last)) {
|
||||
//TODO: Show error message;
|
||||
return;
|
||||
}
|
||||
final mimeType = lookupMimeType(file.path) ?? '';
|
||||
late Uint8List fileBytes;
|
||||
|
||||
Reference in New Issue
Block a user