mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2025-12-06 09:15:48 -06:00
update viewer impl
This commit is contained in:
@@ -34,13 +34,6 @@ if (keystorePropertiesFile.exists()) {
|
|||||||
android {
|
android {
|
||||||
compileSdkVersion 33
|
compileSdkVersion 33
|
||||||
|
|
||||||
packagingOptions {
|
|
||||||
pickFirst '**/x86/libpdfium.so'
|
|
||||||
pickFirst '**/x86_64/libpdfium.so'
|
|
||||||
pickFirst '**/armeabi-v7a/libpdfium.so'
|
|
||||||
pickFirst '**/arm64-v8a/libpdfium.so'
|
|
||||||
}
|
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
// Required for flutter_local_notifications
|
// Required for flutter_local_notifications
|
||||||
coreLibraryDesugaringEnabled true
|
coreLibraryDesugaringEnabled true
|
||||||
|
|||||||
198
assets/example/sample.pdf
Normal file
198
assets/example/sample.pdf
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
%PDF-1.3
|
||||||
|
%<25><><EFBFBD><EFBFBD>
|
||||||
|
|
||||||
|
1 0 obj
|
||||||
|
<<
|
||||||
|
/Type /Catalog
|
||||||
|
/Outlines 2 0 R
|
||||||
|
/Pages 3 0 R
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
2 0 obj
|
||||||
|
<<
|
||||||
|
/Type /Outlines
|
||||||
|
/Count 0
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
3 0 obj
|
||||||
|
<<
|
||||||
|
/Type /Pages
|
||||||
|
/Count 2
|
||||||
|
/Kids [ 4 0 R 6 0 R ]
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
4 0 obj
|
||||||
|
<<
|
||||||
|
/Type /Page
|
||||||
|
/Parent 3 0 R
|
||||||
|
/Resources <<
|
||||||
|
/Font <<
|
||||||
|
/F1 9 0 R
|
||||||
|
>>
|
||||||
|
/ProcSet 8 0 R
|
||||||
|
>>
|
||||||
|
/MediaBox [0 0 612.0000 792.0000]
|
||||||
|
/Contents 5 0 R
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
5 0 obj
|
||||||
|
<< /Length 1074 >>
|
||||||
|
stream
|
||||||
|
2 J
|
||||||
|
BT
|
||||||
|
0 0 0 rg
|
||||||
|
/F1 0027 Tf
|
||||||
|
57.3750 722.2800 Td
|
||||||
|
( A Simple PDF File ) Tj
|
||||||
|
ET
|
||||||
|
BT
|
||||||
|
/F1 0010 Tf
|
||||||
|
69.2500 688.6080 Td
|
||||||
|
( This is a small demonstration .pdf file - ) Tj
|
||||||
|
ET
|
||||||
|
BT
|
||||||
|
/F1 0010 Tf
|
||||||
|
69.2500 664.7040 Td
|
||||||
|
( just for use in the Virtual Mechanics tutorials. More text. And more ) Tj
|
||||||
|
ET
|
||||||
|
BT
|
||||||
|
/F1 0010 Tf
|
||||||
|
69.2500 652.7520 Td
|
||||||
|
( text. And more text. And more text. And more text. ) Tj
|
||||||
|
ET
|
||||||
|
BT
|
||||||
|
/F1 0010 Tf
|
||||||
|
69.2500 628.8480 Td
|
||||||
|
( And more text. And more text. And more text. And more text. And more ) Tj
|
||||||
|
ET
|
||||||
|
BT
|
||||||
|
/F1 0010 Tf
|
||||||
|
69.2500 616.8960 Td
|
||||||
|
( text. And more text. Boring, zzzzz. And more text. And more text. And ) Tj
|
||||||
|
ET
|
||||||
|
BT
|
||||||
|
/F1 0010 Tf
|
||||||
|
69.2500 604.9440 Td
|
||||||
|
( more text. And more text. And more text. And more text. And more text. ) Tj
|
||||||
|
ET
|
||||||
|
BT
|
||||||
|
/F1 0010 Tf
|
||||||
|
69.2500 592.9920 Td
|
||||||
|
( And more text. And more text. ) Tj
|
||||||
|
ET
|
||||||
|
BT
|
||||||
|
/F1 0010 Tf
|
||||||
|
69.2500 569.0880 Td
|
||||||
|
( And more text. And more text. And more text. And more text. And more ) Tj
|
||||||
|
ET
|
||||||
|
BT
|
||||||
|
/F1 0010 Tf
|
||||||
|
69.2500 557.1360 Td
|
||||||
|
( text. And more text. And more text. Even more. Continued on page 2 ...) Tj
|
||||||
|
ET
|
||||||
|
endstream
|
||||||
|
endobj
|
||||||
|
|
||||||
|
6 0 obj
|
||||||
|
<<
|
||||||
|
/Type /Page
|
||||||
|
/Parent 3 0 R
|
||||||
|
/Resources <<
|
||||||
|
/Font <<
|
||||||
|
/F1 9 0 R
|
||||||
|
>>
|
||||||
|
/ProcSet 8 0 R
|
||||||
|
>>
|
||||||
|
/MediaBox [0 0 612.0000 792.0000]
|
||||||
|
/Contents 7 0 R
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
7 0 obj
|
||||||
|
<< /Length 676 >>
|
||||||
|
stream
|
||||||
|
2 J
|
||||||
|
BT
|
||||||
|
0 0 0 rg
|
||||||
|
/F1 0027 Tf
|
||||||
|
57.3750 722.2800 Td
|
||||||
|
( Simple PDF File 2 ) Tj
|
||||||
|
ET
|
||||||
|
BT
|
||||||
|
/F1 0010 Tf
|
||||||
|
69.2500 688.6080 Td
|
||||||
|
( ...continued from page 1. Yet more text. And more text. And more text. ) Tj
|
||||||
|
ET
|
||||||
|
BT
|
||||||
|
/F1 0010 Tf
|
||||||
|
69.2500 676.6560 Td
|
||||||
|
( And more text. And more text. And more text. And more text. And more ) Tj
|
||||||
|
ET
|
||||||
|
BT
|
||||||
|
/F1 0010 Tf
|
||||||
|
69.2500 664.7040 Td
|
||||||
|
( text. Oh, how boring typing this stuff. But not as boring as watching ) Tj
|
||||||
|
ET
|
||||||
|
BT
|
||||||
|
/F1 0010 Tf
|
||||||
|
69.2500 652.7520 Td
|
||||||
|
( paint dry. And more text. And more text. And more text. And more text. ) Tj
|
||||||
|
ET
|
||||||
|
BT
|
||||||
|
/F1 0010 Tf
|
||||||
|
69.2500 640.8000 Td
|
||||||
|
( Boring. More, a little more text. The end, and just as well. ) Tj
|
||||||
|
ET
|
||||||
|
endstream
|
||||||
|
endobj
|
||||||
|
|
||||||
|
8 0 obj
|
||||||
|
[/PDF /Text]
|
||||||
|
endobj
|
||||||
|
|
||||||
|
9 0 obj
|
||||||
|
<<
|
||||||
|
/Type /Font
|
||||||
|
/Subtype /Type1
|
||||||
|
/Name /F1
|
||||||
|
/BaseFont /Helvetica
|
||||||
|
/Encoding /WinAnsiEncoding
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
10 0 obj
|
||||||
|
<<
|
||||||
|
/Creator (Rave \(http://www.nevrona.com/rave\))
|
||||||
|
/Producer (Nevrona Designs)
|
||||||
|
/CreationDate (D:20060301072826)
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
xref
|
||||||
|
0 11
|
||||||
|
0000000000 65535 f
|
||||||
|
0000000019 00000 n
|
||||||
|
0000000093 00000 n
|
||||||
|
0000000147 00000 n
|
||||||
|
0000000222 00000 n
|
||||||
|
0000000390 00000 n
|
||||||
|
0000001522 00000 n
|
||||||
|
0000001690 00000 n
|
||||||
|
0000002423 00000 n
|
||||||
|
0000002456 00000 n
|
||||||
|
0000002574 00000 n
|
||||||
|
|
||||||
|
trailer
|
||||||
|
<<
|
||||||
|
/Size 11
|
||||||
|
/Root 1 0 R
|
||||||
|
/Info 10 0 R
|
||||||
|
>>
|
||||||
|
|
||||||
|
startxref
|
||||||
|
2714
|
||||||
|
%%EOF
|
||||||
@@ -85,7 +85,7 @@ class FileService {
|
|||||||
bool create = false,
|
bool create = false,
|
||||||
}) async {
|
}) async {
|
||||||
final dir = getDirectory(type);
|
final dir = getDirectory(type);
|
||||||
final filename = (fileName ?? const Uuid().v1()) + '.$extension';
|
final filename = '${fileName ?? const Uuid().v1()}.$extension';
|
||||||
final file = File(p.join(dir.path, filename));
|
final file = File(p.join(dir.path, filename));
|
||||||
if (create) {
|
if (create) {
|
||||||
await file.create(recursive: true);
|
await file.create(recursive: true);
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ class DocumentDetailsCubit extends Cubit<DocumentDetailsState> {
|
|||||||
if (!file.existsSync()) {
|
if (!file.existsSync()) {
|
||||||
file.createSync();
|
file.createSync();
|
||||||
await _api.downloadToFile(
|
await _api.downloadToFile(
|
||||||
state.document!,
|
state.document!.id,
|
||||||
file.path,
|
file.path,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -219,7 +219,7 @@ class DocumentDetailsCubit extends Cubit<DocumentDetailsState> {
|
|||||||
// );
|
// );
|
||||||
|
|
||||||
await _api.downloadToFile(
|
await _api.downloadToFile(
|
||||||
state.document!,
|
state.document!.id,
|
||||||
targetPath,
|
targetPath,
|
||||||
original: downloadOriginal,
|
original: downloadOriginal,
|
||||||
onProgressChanged: (progress) {
|
onProgressChanged: (progress) {
|
||||||
@@ -255,7 +255,7 @@ class DocumentDetailsCubit extends Cubit<DocumentDetailsState> {
|
|||||||
FileService.instance.temporaryDirectory,
|
FileService.instance.temporaryDirectory,
|
||||||
);
|
);
|
||||||
await _api.downloadToFile(
|
await _api.downloadToFile(
|
||||||
state.document!,
|
state.document!.id,
|
||||||
filePath,
|
filePath,
|
||||||
original: shareOriginal,
|
original: shareOriginal,
|
||||||
);
|
);
|
||||||
@@ -282,7 +282,7 @@ class DocumentDetailsCubit extends Cubit<DocumentDetailsState> {
|
|||||||
FileService.instance.temporaryDirectory,
|
FileService.instance.temporaryDirectory,
|
||||||
);
|
);
|
||||||
await _api.downloadToFile(
|
await _api.downloadToFile(
|
||||||
state.document!,
|
state.document!.id,
|
||||||
filePath,
|
filePath,
|
||||||
original: false,
|
original: false,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -24,10 +24,9 @@ import 'package:paperless_mobile/routing/routes/labels_route.dart';
|
|||||||
import 'package:paperless_mobile/routing/routes/shells/authenticated_route.dart';
|
import 'package:paperless_mobile/routing/routes/shells/authenticated_route.dart';
|
||||||
|
|
||||||
typedef ItemBuilder<T> = Widget Function(BuildContext context, T itemData);
|
typedef ItemBuilder<T> = Widget Function(BuildContext context, T itemData);
|
||||||
|
|
||||||
class DocumentEditPage extends StatefulWidget {
|
class DocumentEditPage extends StatefulWidget {
|
||||||
const DocumentEditPage({
|
const DocumentEditPage({super.key});
|
||||||
super.key
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<DocumentEditPage> createState() => _DocumentEditPageState();
|
State<DocumentEditPage> createState() => _DocumentEditPageState();
|
||||||
|
|||||||
@@ -1,10 +1,160 @@
|
|||||||
import 'dart:math';
|
// import 'dart:async';
|
||||||
|
// import 'dart:developer';
|
||||||
|
|
||||||
|
// import 'package:flutter/foundation.dart';
|
||||||
|
// import 'package:flutter/material.dart';
|
||||||
|
// import 'package:flutter_animate/flutter_animate.dart';
|
||||||
|
// import 'package:paperless_mobile/core/extensions/flutter_extensions.dart';
|
||||||
|
// import 'package:pdfx/pdfx.dart';
|
||||||
|
|
||||||
|
// class DocumentView extends StatefulWidget {
|
||||||
|
// final String? filePath;
|
||||||
|
// final Future<Uint8List>? bytes;
|
||||||
|
// final String? title;
|
||||||
|
// final bool showAppBar;
|
||||||
|
// final bool showControls;
|
||||||
|
// const DocumentView({
|
||||||
|
// super.key,
|
||||||
|
// this.bytes,
|
||||||
|
// this.showAppBar = true,
|
||||||
|
// this.showControls = true,
|
||||||
|
// this.title,
|
||||||
|
// this.filePath,
|
||||||
|
// }) : assert(bytes != null || filePath != null);
|
||||||
|
|
||||||
|
// @override
|
||||||
|
// State<DocumentView> createState() => _DocumentViewState();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// class _DocumentViewState extends State<DocumentView> {
|
||||||
|
// late final PdfController _controller;
|
||||||
|
// int _currentPage = 1;
|
||||||
|
// int? _totalPages;
|
||||||
|
// @override
|
||||||
|
// void initState() {
|
||||||
|
// super.initState();
|
||||||
|
// Future<PdfDocument> document;
|
||||||
|
// document = PdfDocument.openAsset("assets/example/sample.pdf");
|
||||||
|
// // if (widget.bytes != null) {
|
||||||
|
// // document = widget.bytes!.then((value) => PdfDocument.openData(value));
|
||||||
|
// // } else {
|
||||||
|
// // document = PdfDocument.openFile(widget.filePath!);
|
||||||
|
// // }
|
||||||
|
// _controller = PdfController(document: document);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @override
|
||||||
|
// void didChangeDependencies() {
|
||||||
|
// super.didChangeDependencies();
|
||||||
|
// log("Did change dependencies LOL");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @override
|
||||||
|
// void dispose() {
|
||||||
|
// _controller.dispose();
|
||||||
|
// super.dispose();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @override
|
||||||
|
// Widget build(BuildContext context) {
|
||||||
|
// final pageTransitionDuration = MediaQuery.disableAnimationsOf(context)
|
||||||
|
// ? 0.milliseconds
|
||||||
|
// : 100.milliseconds;
|
||||||
|
// final canGoToNextPage = _totalPages != null && _currentPage < _totalPages!;
|
||||||
|
// final canGoToPreviousPage =
|
||||||
|
// _controller.pagesCount != null && _currentPage > 1;
|
||||||
|
// return Scaffold(
|
||||||
|
// appBar: widget.showAppBar
|
||||||
|
// ? AppBar(
|
||||||
|
// title: widget.title != null ? Text(widget.title!) : null,
|
||||||
|
// )
|
||||||
|
// : null,
|
||||||
|
// bottomNavigationBar: widget.showControls
|
||||||
|
// ? BottomAppBar(
|
||||||
|
// child: Row(
|
||||||
|
// children: [
|
||||||
|
// Flexible(
|
||||||
|
// child: Row(
|
||||||
|
// children: [
|
||||||
|
// IconButton.filled(
|
||||||
|
// onPressed: canGoToPreviousPage
|
||||||
|
// ? () async {
|
||||||
|
// await _controller.previousPage(
|
||||||
|
// duration: pageTransitionDuration,
|
||||||
|
// curve: Curves.easeOut,
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// : null,
|
||||||
|
// icon: const Icon(Icons.arrow_left),
|
||||||
|
// ),
|
||||||
|
// const SizedBox(width: 16),
|
||||||
|
// IconButton.filled(
|
||||||
|
// onPressed: canGoToNextPage
|
||||||
|
// ? () async {
|
||||||
|
// await _controller.nextPage(
|
||||||
|
// duration: pageTransitionDuration,
|
||||||
|
// curve: Curves.easeOut,
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// : null,
|
||||||
|
// icon: const Icon(Icons.arrow_right),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// // PdfPageNumber(
|
||||||
|
// // controller: _controller,
|
||||||
|
// // builder: (context, loadingState, page, pagesCount) {
|
||||||
|
// // if (loadingState != PdfLoadingState.success) {
|
||||||
|
// // return const Text("-/-");
|
||||||
|
// // }
|
||||||
|
// // return Text(
|
||||||
|
// // "$page/$pagesCount",
|
||||||
|
// // style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
// // ).padded();
|
||||||
|
// // },
|
||||||
|
// // ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// )
|
||||||
|
// : null,
|
||||||
|
// body: PdfView(
|
||||||
|
// builders: PdfViewBuilders<DefaultBuilderOptions>(
|
||||||
|
// options: const DefaultBuilderOptions(),
|
||||||
|
// documentLoaderBuilder: (_) =>
|
||||||
|
// const Center(child: CircularProgressIndicator()),
|
||||||
|
// pageLoaderBuilder: (_) =>
|
||||||
|
// const Center(child: CircularProgressIndicator()),
|
||||||
|
// errorBuilder: (p0, error) {
|
||||||
|
// return Center(
|
||||||
|
// child: Text(error.toString()),
|
||||||
|
// );
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
// controller: _controller,
|
||||||
|
// ),
|
||||||
|
// // PdfView(
|
||||||
|
// // controller: _controller,
|
||||||
|
// // onDocumentLoaded: (document) {
|
||||||
|
// // setState(() {
|
||||||
|
// // _totalPages = document.pagesCount;
|
||||||
|
// // });
|
||||||
|
// // },
|
||||||
|
// // onPageChanged: (page) {
|
||||||
|
// // setState(() {
|
||||||
|
// // _currentPage = page;
|
||||||
|
// // });
|
||||||
|
// // },
|
||||||
|
// // ),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_animate/flutter_animate.dart';
|
import 'package:flutter_animate/flutter_animate.dart';
|
||||||
import 'package:paperless_mobile/core/extensions/flutter_extensions.dart';
|
import 'package:paperless_mobile/core/extensions/flutter_extensions.dart';
|
||||||
import 'package:pdfrx/pdfrx.dart';
|
import 'package:pdfx/pdfx.dart';
|
||||||
|
|
||||||
class DocumentView extends StatefulWidget {
|
class DocumentView extends StatefulWidget {
|
||||||
final Future<Uint8List> documentBytes;
|
final Future<Uint8List> documentBytes;
|
||||||
@@ -12,37 +162,27 @@ class DocumentView extends StatefulWidget {
|
|||||||
final bool showAppBar;
|
final bool showAppBar;
|
||||||
final bool showControls;
|
final bool showControls;
|
||||||
const DocumentView({
|
const DocumentView({
|
||||||
super.key,
|
Key? key,
|
||||||
required this.documentBytes,
|
required this.documentBytes,
|
||||||
this.showAppBar = true,
|
this.showAppBar = true,
|
||||||
this.showControls = true,
|
this.showControls = true,
|
||||||
this.title,
|
this.title,
|
||||||
});
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<DocumentView> createState() => _DocumentViewState();
|
State<DocumentView> createState() => _DocumentViewState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _DocumentViewState extends State<DocumentView> {
|
class _DocumentViewState extends State<DocumentView> {
|
||||||
final PdfViewerController _controller = PdfViewerController();
|
late final PdfController _controller;
|
||||||
int _currentPage = 1;
|
int _currentPage = 1;
|
||||||
int? _totalPages;
|
int? _totalPages;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_controller.addListener(() {
|
final document =
|
||||||
if (mounted) {
|
widget.documentBytes.then((value) => PdfDocument.openData(value));
|
||||||
if (_controller.pageNumber != null) {
|
_controller = PdfController(document: document);
|
||||||
setState(() {
|
|
||||||
_currentPage = _controller.pageNumber!;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
setState(() {
|
|
||||||
_totalPages = _controller.pages.length;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -57,7 +197,8 @@ class _DocumentViewState extends State<DocumentView> {
|
|||||||
? 0.milliseconds
|
? 0.milliseconds
|
||||||
: 100.milliseconds;
|
: 100.milliseconds;
|
||||||
final canGoToNextPage = _totalPages != null && _currentPage < _totalPages!;
|
final canGoToNextPage = _totalPages != null && _currentPage < _totalPages!;
|
||||||
final canGoToPreviousPage = _totalPages != null && _currentPage > 1;
|
final canGoToPreviousPage =
|
||||||
|
_controller.pagesCount != null && _currentPage > 1;
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: widget.showAppBar
|
appBar: widget.showAppBar
|
||||||
? AppBar(
|
? AppBar(
|
||||||
@@ -74,8 +215,9 @@ class _DocumentViewState extends State<DocumentView> {
|
|||||||
IconButton.filled(
|
IconButton.filled(
|
||||||
onPressed: canGoToPreviousPage
|
onPressed: canGoToPreviousPage
|
||||||
? () async {
|
? () async {
|
||||||
await _controller.goToPage(
|
await _controller.previousPage(
|
||||||
pageNumber: _currentPage - 1,
|
duration: pageTransitionDuration,
|
||||||
|
curve: Curves.easeOut,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
@@ -85,8 +227,9 @@ class _DocumentViewState extends State<DocumentView> {
|
|||||||
IconButton.filled(
|
IconButton.filled(
|
||||||
onPressed: canGoToNextPage
|
onPressed: canGoToNextPage
|
||||||
? () async {
|
? () async {
|
||||||
await _controller.goToPage(
|
await _controller.nextPage(
|
||||||
pageNumber: _currentPage + 1,
|
duration: pageTransitionDuration,
|
||||||
|
curve: Curves.easeOut,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
@@ -95,13 +238,14 @@ class _DocumentViewState extends State<DocumentView> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Builder(
|
PdfPageNumber(
|
||||||
builder: (context) {
|
controller: _controller,
|
||||||
if (_totalPages == null) {
|
builder: (context, loadingState, page, pagesCount) {
|
||||||
|
if (loadingState != PdfLoadingState.success) {
|
||||||
return const Text("-/-");
|
return const Text("-/-");
|
||||||
}
|
}
|
||||||
return Text(
|
return Text(
|
||||||
"$_currentPage/$_totalPages",
|
"$page/$pagesCount",
|
||||||
style: Theme.of(context).textTheme.titleMedium,
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
).padded();
|
).padded();
|
||||||
},
|
},
|
||||||
@@ -110,61 +254,17 @@ class _DocumentViewState extends State<DocumentView> {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
body: FutureBuilder<Uint8List>(
|
body: PdfView(
|
||||||
future: widget.documentBytes,
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
if (!snapshot.hasData) {
|
|
||||||
return Center(
|
|
||||||
child: CircularProgressIndicator(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return PdfViewer.data(
|
|
||||||
snapshot.data!,
|
|
||||||
controller: _controller,
|
controller: _controller,
|
||||||
anchor: PdfPageAnchor.all,
|
onDocumentLoaded: (document) {
|
||||||
displayParams: PdfViewerParams(
|
setState(() {
|
||||||
backgroundColor: Theme.of(context).colorScheme.background,
|
_totalPages = document.pagesCount;
|
||||||
margin: 0,
|
});
|
||||||
layoutPages: (pages, params) {
|
|
||||||
final height =
|
|
||||||
pages.fold(0.0, (prev, page) => max(prev, page.height)) +
|
|
||||||
params.margin * 2;
|
|
||||||
final pageLayouts = <Rect>[];
|
|
||||||
double x = params.margin;
|
|
||||||
for (var page in pages) {
|
|
||||||
pageLayouts.add(
|
|
||||||
Rect.fromLTWH(
|
|
||||||
x,
|
|
||||||
(height - page.height) / 2, // center vertically
|
|
||||||
page.width,
|
|
||||||
page.height,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
x += page.width + params.margin;
|
|
||||||
}
|
|
||||||
return PdfPageLayout(
|
|
||||||
pageLayouts: pageLayouts,
|
|
||||||
documentSize: Size(x, height),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
),
|
onPageChanged: (page) {
|
||||||
// controller: _controller,
|
setState(() {
|
||||||
// onDocumentLoaded: (document) {
|
_currentPage = page;
|
||||||
// if (mounted) {
|
});
|
||||||
// setState(() {
|
|
||||||
// _totalPages = document.pagesCount;
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// onPageChanged: (page) {
|
|
||||||
// if (mounted) {
|
|
||||||
// setState(() {
|
|
||||||
// _currentPage = page;
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
85
lib/features/documents/view/pages/pdfrx_document_view.dart
Normal file
85
lib/features/documents/view/pages/pdfrx_document_view.dart
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:math';
|
||||||
|
import 'dart:typed_data';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:pdfrx/pdfrx.dart';
|
||||||
|
|
||||||
|
class PdfrxDocumentView extends StatefulWidget {
|
||||||
|
final Future<Uint8List> bytes;
|
||||||
|
|
||||||
|
const PdfrxDocumentView({super.key, required this.bytes});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<PdfrxDocumentView> createState() => _PdfrxDocumentViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PdfrxDocumentViewState extends State<PdfrxDocumentView> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return PdfViewer.asset(
|
||||||
|
// snapshot.data!,
|
||||||
|
'assets/example/sample.pdf',
|
||||||
|
displayParams: PdfViewerParams(
|
||||||
|
layoutPages: (pages, params) {
|
||||||
|
final height =
|
||||||
|
pages.fold(0.0, (prev, page) => max(prev, page.height)) +
|
||||||
|
params.margin * 2;
|
||||||
|
final pageLayouts = <Rect>[];
|
||||||
|
double x = params.margin;
|
||||||
|
for (var page in pages) {
|
||||||
|
pageLayouts.add(
|
||||||
|
Rect.fromLTWH(
|
||||||
|
x,
|
||||||
|
(height - page.height) / 2, // center vertically
|
||||||
|
page.width,
|
||||||
|
page.height,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
x += page.width + params.margin;
|
||||||
|
}
|
||||||
|
return PdfPageLayout(
|
||||||
|
pageLayouts: pageLayouts,
|
||||||
|
documentSize: Size(x, height),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return FutureBuilder(
|
||||||
|
future: widget.bytes,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (!snapshot.hasData) {
|
||||||
|
return const Center(child: CircularProgressIndicator());
|
||||||
|
}
|
||||||
|
return PdfViewer.asset(
|
||||||
|
// snapshot.data!,
|
||||||
|
'assets/example/sample.pdf',
|
||||||
|
displayParams: PdfViewerParams(
|
||||||
|
layoutPages: (pages, params) {
|
||||||
|
final height =
|
||||||
|
pages.fold(0.0, (prev, page) => max(prev, page.height)) +
|
||||||
|
params.margin * 2;
|
||||||
|
final pageLayouts = <Rect>[];
|
||||||
|
double x = params.margin;
|
||||||
|
for (var page in pages) {
|
||||||
|
pageLayouts.add(
|
||||||
|
Rect.fromLTWH(
|
||||||
|
x,
|
||||||
|
(height - page.height) / 2, // center vertically
|
||||||
|
page.width,
|
||||||
|
page.height,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
x += page.width + params.margin;
|
||||||
|
}
|
||||||
|
return PdfPageLayout(
|
||||||
|
pageLayouts: pageLayouts,
|
||||||
|
documentSize: Size(x, height),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||||
|
import 'package:paperless_mobile/core/service/file_service.dart';
|
||||||
import 'package:paperless_mobile/features/document_bulk_action/cubit/document_bulk_action_cubit.dart';
|
import 'package:paperless_mobile/features/document_bulk_action/cubit/document_bulk_action_cubit.dart';
|
||||||
import 'package:paperless_mobile/features/document_bulk_action/view/widgets/fullscreen_bulk_edit_label_page.dart';
|
import 'package:paperless_mobile/features/document_bulk_action/view/widgets/fullscreen_bulk_edit_label_page.dart';
|
||||||
import 'package:paperless_mobile/features/document_bulk_action/view/widgets/fullscreen_bulk_edit_tags_widget.dart';
|
import 'package:paperless_mobile/features/document_bulk_action/view/widgets/fullscreen_bulk_edit_tags_widget.dart';
|
||||||
@@ -13,6 +14,7 @@ import 'package:paperless_mobile/features/document_edit/cubit/document_edit_cubi
|
|||||||
import 'package:paperless_mobile/features/document_edit/view/document_edit_page.dart';
|
import 'package:paperless_mobile/features/document_edit/view/document_edit_page.dart';
|
||||||
import 'package:paperless_mobile/features/documents/view/pages/document_view.dart';
|
import 'package:paperless_mobile/features/documents/view/pages/document_view.dart';
|
||||||
import 'package:paperless_mobile/features/documents/view/pages/documents_page.dart';
|
import 'package:paperless_mobile/features/documents/view/pages/documents_page.dart';
|
||||||
|
import 'package:paperless_mobile/features/documents/view/pages/pdfrx_document_view.dart';
|
||||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||||
import 'package:paperless_mobile/routing/navigation_keys.dart';
|
import 'package:paperless_mobile/routing/navigation_keys.dart';
|
||||||
import 'package:paperless_mobile/theme.dart';
|
import 'package:paperless_mobile/theme.dart';
|
||||||
@@ -110,6 +112,8 @@ class DocumentPreviewRoute extends GoRouteData {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, GoRouterState state) {
|
Widget build(BuildContext context, GoRouterState state) {
|
||||||
|
return PdfrxDocumentView(
|
||||||
|
bytes: context.read<PaperlessDocumentsApi>().downloadDocument(id));
|
||||||
return DocumentView(
|
return DocumentView(
|
||||||
documentBytes: context.read<PaperlessDocumentsApi>().downloadDocument(id),
|
documentBytes: context.read<PaperlessDocumentsApi>().downloadDocument(id),
|
||||||
title: title,
|
title: title,
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ abstract class PaperlessDocumentsApi {
|
|||||||
String getThumbnailUrl(int docId);
|
String getThumbnailUrl(int docId);
|
||||||
Future<Uint8List> downloadDocument(int id, {bool original});
|
Future<Uint8List> downloadDocument(int id, {bool original});
|
||||||
Future<void> downloadToFile(
|
Future<void> downloadToFile(
|
||||||
DocumentModel document,
|
int id,
|
||||||
String localFilePath, {
|
String localFilePath, {
|
||||||
bool original = false,
|
bool original = false,
|
||||||
void Function(double progress)? onProgressChanged,
|
void Function(double progress)? onProgressChanged,
|
||||||
|
|||||||
@@ -223,14 +223,14 @@ class PaperlessDocumentsApiImpl implements PaperlessDocumentsApi {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> downloadToFile(
|
Future<void> downloadToFile(
|
||||||
DocumentModel document,
|
int id,
|
||||||
String localFilePath, {
|
String localFilePath, {
|
||||||
bool original = false,
|
bool original = false,
|
||||||
void Function(double)? onProgressChanged,
|
void Function(double)? onProgressChanged,
|
||||||
}) async {
|
}) async {
|
||||||
try {
|
try {
|
||||||
final response = await client.download(
|
final response = await client.download(
|
||||||
"/api/documents/${document.id}/download/",
|
"/api/documents/$id/download/",
|
||||||
localFilePath,
|
localFilePath,
|
||||||
onReceiveProgress: (count, total) =>
|
onReceiveProgress: (count, total) =>
|
||||||
onProgressChanged?.call(count / total),
|
onProgressChanged?.call(count / total),
|
||||||
|
|||||||
@@ -1191,10 +1191,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: path_provider
|
name: path_provider
|
||||||
sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa
|
sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.1"
|
version: "2.1.2"
|
||||||
path_provider_android:
|
path_provider_android:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1247,10 +1247,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: pdfrx
|
name: pdfrx
|
||||||
sha256: "001036f0b97214ec0a34bf02414f4f4a260b60ccc577d1bff97366b3a2e7b4f6"
|
sha256: "7b34f58ec0f8959cd99a6ff3de8fd1a54824823462c7a118fa55bcb42ca45422"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.3"
|
version: "0.4.6"
|
||||||
pdfx:
|
pdfx:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ dependencies:
|
|||||||
flutter_secure_storage: ^9.0.0
|
flutter_secure_storage: ^9.0.0
|
||||||
sliver_tools: ^0.2.10
|
sliver_tools: ^0.2.10
|
||||||
webview_flutter: ^4.2.1
|
webview_flutter: ^4.2.1
|
||||||
printing: ^5.11.0
|
printing: ^5.11.1
|
||||||
go_router: ^13.0.1
|
go_router: ^13.0.1
|
||||||
fl_chart: ^0.66.0
|
fl_chart: ^0.66.0
|
||||||
palette_generator: ^0.3.3+2
|
palette_generator: ^0.3.3+2
|
||||||
@@ -107,7 +107,7 @@ dependencies:
|
|||||||
ref: '4be9de9ffed5398fd7d5f44bbb07dcd3d3f1711b'
|
ref: '4be9de9ffed5398fd7d5f44bbb07dcd3d3f1711b'
|
||||||
path: packages/pdfx
|
path: packages/pdfx
|
||||||
markdown: ^7.1.1
|
markdown: ^7.1.1
|
||||||
pdfrx: ^0.4.3
|
pdfrx: ^0.4.6
|
||||||
|
|
||||||
dependency_overrides:
|
dependency_overrides:
|
||||||
intl: ^0.18.1
|
intl: ^0.18.1
|
||||||
@@ -158,6 +158,7 @@ flutter:
|
|||||||
- test/fixtures/preview/
|
- test/fixtures/preview/
|
||||||
- test/fixtures/document_types/
|
- test/fixtures/document_types/
|
||||||
- assets/changelogs/
|
- assets/changelogs/
|
||||||
|
- assets/example/
|
||||||
|
|
||||||
fonts:
|
fonts:
|
||||||
- family: RobotoMono
|
- family: RobotoMono
|
||||||
|
|||||||
Reference in New Issue
Block a user