mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2025-12-07 13:15:55 -06:00
feat: Add print feature, refine gradient on details page
This commit is contained in:
@@ -11,6 +11,7 @@ import 'package:paperless_mobile/core/repository/label_repository.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:printing/printing.dart';
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
import 'package:cross_file/cross_file.dart';
|
||||
|
||||
@@ -98,6 +99,7 @@ class DocumentDetailsCubit extends Cubit<DocumentDetailsState> {
|
||||
|
||||
Future<ResultType> openDocumentInSystemViewer() async {
|
||||
final cacheDir = await FileService.temporaryDirectory;
|
||||
//TODO: Why is this cleared here?
|
||||
await FileService.clearDirectoryContent(PaperlessDirectoryType.temporary);
|
||||
if (state.metaData == null) {
|
||||
await loadMetaData();
|
||||
@@ -199,6 +201,26 @@ class DocumentDetailsCubit extends Cubit<DocumentDetailsState> {
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> printDocument() async {
|
||||
if (state.metaData == null) {
|
||||
await loadMetaData();
|
||||
}
|
||||
final filePath = _buildDownloadFilePath(false, await FileService.temporaryDirectory);
|
||||
await _api.downloadToFile(
|
||||
state.document,
|
||||
filePath,
|
||||
original: false,
|
||||
);
|
||||
final file = File(filePath);
|
||||
if (!file.existsSync()) {
|
||||
throw Exception("An error occurred while downloading the document.");
|
||||
}
|
||||
Printing.layoutPdf(
|
||||
name: state.document.title,
|
||||
onLayout: (format) => file.readAsBytesSync(),
|
||||
);
|
||||
}
|
||||
|
||||
String _buildDownloadFilePath(bool original, Directory dir) {
|
||||
final description = FileDescription.fromPath(
|
||||
state.metaData!.mediaFilename.replaceAll("/", " "), // Flatten directory structure
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:open_filex/open_filex.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart';
|
||||
@@ -44,11 +46,6 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
||||
|
||||
final _pagingScrollController = ScrollController();
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final apiVersion = context.watch<ApiVersion>();
|
||||
@@ -87,22 +84,24 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
||||
alignment: Alignment.topCenter,
|
||||
children: [
|
||||
BlocBuilder<DocumentDetailsCubit, DocumentDetailsState>(
|
||||
builder: (context, state) => Positioned.fill(
|
||||
child: DocumentPreview(
|
||||
document: state.document,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
builder: (context, state) {
|
||||
return Positioned.fill(
|
||||
child: DocumentPreview(
|
||||
document: state.document,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
Positioned.fill(
|
||||
top: 0,
|
||||
child: Container(
|
||||
height: 100,
|
||||
child: DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
Colors.black.withOpacity(0.7),
|
||||
Colors.black.withOpacity(0.2),
|
||||
Theme.of(context).colorScheme.background.withOpacity(0.8),
|
||||
Theme.of(context).colorScheme.background.withOpacity(0.5),
|
||||
Colors.transparent,
|
||||
Colors.transparent,
|
||||
Colors.transparent,
|
||||
],
|
||||
@@ -310,7 +309,7 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
||||
IconButton(
|
||||
tooltip: S.of(context)!.previewTooltip,
|
||||
icon: const Icon(Icons.visibility),
|
||||
onPressed: (isConnected && false) ? () => _onOpen(state.document) : null,
|
||||
onPressed: (isConnected) ? () => _onOpen(state.document) : null,
|
||||
).paddedOnly(right: 4.0),
|
||||
IconButton(
|
||||
tooltip: S.of(context)!.openInSystemViewer,
|
||||
@@ -318,6 +317,11 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
||||
onPressed: isConnected ? _onOpenFileInSystemViewer : null,
|
||||
).paddedOnly(right: 4.0),
|
||||
DocumentShareButton(document: state.document),
|
||||
IconButton(
|
||||
tooltip: "Print", //TODO: INTL
|
||||
onPressed: () => context.read<DocumentDetailsCubit>().printDocument(),
|
||||
icon: const Icon(Icons.print),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
@@ -404,7 +408,8 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (_) => DocumentView(
|
||||
documentBytes: context.read<PaperlessDocumentsApi>().getPreview(document.id),
|
||||
documentBytes: context.read<PaperlessDocumentsApi>().download(document),
|
||||
title: document.title,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -120,6 +120,7 @@ class _ScannerPageState extends State<ScannerPage> with SingleTickerProviderStat
|
||||
? () => Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => DocumentView(
|
||||
|
||||
documentBytes: _assembleFileBytes(
|
||||
state,
|
||||
forcePdf: true,
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_pdfview/flutter_pdfview.dart';
|
||||
|
||||
class DocumentView extends StatefulWidget {
|
||||
final Future<Uint8List> documentBytes;
|
||||
|
||||
final String? title;
|
||||
const DocumentView({
|
||||
Key? key,
|
||||
required this.documentBytes,
|
||||
this.title,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
@@ -14,37 +16,90 @@ class DocumentView extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _DocumentViewState extends State<DocumentView> {
|
||||
// late PdfController _pdfController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// _pdfController = PdfController(
|
||||
// document: PdfDocument.openData(
|
||||
// widget.documentBytes,
|
||||
// ),
|
||||
// );
|
||||
}
|
||||
int? _currentPage;
|
||||
int? _totalPages;
|
||||
PDFViewController? _controller;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container();
|
||||
// return Scaffold(
|
||||
// appBar: AppBar(
|
||||
// title: Text(S.of(context)!.preview),
|
||||
// ),
|
||||
// body: PdfView(
|
||||
// builders: PdfViewBuilders<DefaultBuilderOptions>(
|
||||
// options: const DefaultBuilderOptions(
|
||||
// loaderSwitchDuration: Duration(milliseconds: 500),
|
||||
// ),
|
||||
// pageLoaderBuilder: (context) => const Center(
|
||||
// child: CircularProgressIndicator(),
|
||||
// ),
|
||||
// ),
|
||||
// scrollDirection: Axis.vertical,
|
||||
// controller: _pdfController,
|
||||
// ),
|
||||
// );
|
||||
final isInitialized = _controller != null && _currentPage != null && _totalPages != null;
|
||||
final canGoToNextPage = isInitialized && _currentPage! + 1 < _totalPages!;
|
||||
final canGoToPreviousPage = isInitialized && _currentPage! > 0;
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: widget.title != null ? Text(widget.title!) : null,
|
||||
),
|
||||
bottomNavigationBar: BottomAppBar(
|
||||
child: Row(
|
||||
children: [
|
||||
Flexible(
|
||||
child: Row(
|
||||
children: [
|
||||
IconButton.filled(
|
||||
onPressed: canGoToPreviousPage
|
||||
? () {
|
||||
_controller?.setPage(_currentPage! - 1);
|
||||
}
|
||||
: null,
|
||||
icon: const Icon(Icons.arrow_left),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
IconButton.filled(
|
||||
onPressed: canGoToNextPage
|
||||
? () {
|
||||
_controller?.setPage(_currentPage! + 1);
|
||||
}
|
||||
: null,
|
||||
icon: const Icon(Icons.arrow_right),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (_currentPage != null && _totalPages != null)
|
||||
Text(
|
||||
"${_currentPage! + 1}/$_totalPages",
|
||||
style: Theme.of(context).textTheme.labelLarge,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
body: FutureBuilder(
|
||||
future: widget.documentBytes,
|
||||
builder: (context, snapshot) {
|
||||
if (!snapshot.hasData) {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
}
|
||||
return PDFView(
|
||||
pdfData: snapshot.data,
|
||||
defaultPage: 0,
|
||||
enableSwipe: true,
|
||||
fitPolicy: FitPolicy.BOTH,
|
||||
swipeHorizontal: true,
|
||||
onRender: (pages) {
|
||||
setState(() {
|
||||
_currentPage = 0;
|
||||
_totalPages = pages ?? -1;
|
||||
});
|
||||
},
|
||||
onPageChanged: (page, total) {
|
||||
setState(() {
|
||||
_currentPage = page;
|
||||
_totalPages = total;
|
||||
});
|
||||
},
|
||||
onViewCreated: (controller) {
|
||||
_controller = controller;
|
||||
},
|
||||
onError: (error) {
|
||||
print(error.toString());
|
||||
},
|
||||
onPageError: (page, error) {
|
||||
print('$page: ${error.toString()}');
|
||||
},
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,7 @@ Future<void> _initHive() async {
|
||||
}
|
||||
|
||||
void main() async {
|
||||
Paint.enableDithering = true;
|
||||
if (kDebugMode) {
|
||||
// URL: http://localhost:3131
|
||||
// Login: admin:test
|
||||
|
||||
18
pubspec.lock
18
pubspec.lock
@@ -617,6 +617,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.18"
|
||||
flutter_pdfview:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_pdfview
|
||||
sha256: d9735fd8991609910742a25c63a5f87060849e57e60112c677b802ddb64bed72
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
flutter_plugin_android_lifecycle:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1267,6 +1275,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
printing:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: printing
|
||||
sha256: e7c383dca95ee7b88c02dc1c66638628d3dcdc2fb2cc47e7a595facd47e46b56
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.11.0"
|
||||
process:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1802,4 +1818,4 @@ packages:
|
||||
version: "3.1.1"
|
||||
sdks:
|
||||
dart: ">=3.0.0 <4.0.0"
|
||||
flutter: ">=3.7.0"
|
||||
flutter: ">=3.10.0"
|
||||
|
||||
@@ -94,6 +94,8 @@ dependencies:
|
||||
flutter_secure_storage: ^8.0.0
|
||||
sliver_tools: ^0.2.10
|
||||
webview_flutter: ^4.2.1
|
||||
printing: ^5.11.0
|
||||
flutter_pdfview: ^1.3.1
|
||||
|
||||
dependency_overrides:
|
||||
intl: ^0.18.0
|
||||
|
||||
Reference in New Issue
Block a user