diff --git a/lib/features/documents/view/pages/document_view.dart b/lib/features/documents/view/pages/document_view.dart index bda53a14..24322596 100644 --- a/lib/features/documents/view/pages/document_view.dart +++ b/lib/features/documents/view/pages/document_view.dart @@ -1,6 +1,8 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_pdfview/flutter_pdfview.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 Future documentBytes; @@ -20,16 +22,31 @@ class DocumentView extends StatefulWidget { } class _DocumentViewState extends State { - int? _currentPage; + late final PdfController _controller; + int _currentPage = 1; int? _totalPages; - PDFViewController? _controller; + @override + void initState() { + super.initState(); + final document = + widget.documentBytes.then((value) => PdfDocument.openData(value)); + _controller = PdfController(document: document); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } @override Widget build(BuildContext context) { - final isInitialized = - _controller != null && _currentPage != null && _totalPages != null; - final canGoToNextPage = isInitialized && _currentPage! + 1 < _totalPages!; - final canGoToPreviousPage = isInitialized && _currentPage! > 0; + 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( @@ -45,8 +62,11 @@ class _DocumentViewState extends State { children: [ IconButton.filled( onPressed: canGoToPreviousPage - ? () { - _controller?.setPage(_currentPage! - 1); + ? () async { + await _controller.previousPage( + duration: pageTransitionDuration, + curve: Curves.easeOut, + ); } : null, icon: const Icon(Icons.arrow_left), @@ -54,8 +74,11 @@ class _DocumentViewState extends State { const SizedBox(width: 16), IconButton.filled( onPressed: canGoToNextPage - ? () { - _controller?.setPage(_currentPage! + 1); + ? () async { + await _controller.nextPage( + duration: pageTransitionDuration, + curve: Curves.easeOut, + ); } : null, icon: const Icon(Icons.arrow_right), @@ -63,47 +86,35 @@ class _DocumentViewState extends State { ], ), ), - if (_currentPage != null && _totalPages != null) - Text( - "${_currentPage! + 1}/$_totalPages", - style: Theme.of(context).textTheme.labelLarge, - ), + 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: 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; - }, - - ); - }), + body: PdfView( + controller: _controller, + onDocumentLoaded: (document) { + setState(() { + _totalPages = document.pagesCount; + }); + }, + onPageChanged: (page) { + setState(() { + _currentPage = page; + }); + }, + ), ); } } diff --git a/lib/features/documents/view/widgets/document_preview.dart b/lib/features/documents/view/widgets/document_preview.dart index cd260d37..da9f542c 100644 --- a/lib/features/documents/view/widgets/document_preview.dart +++ b/lib/features/documents/view/widgets/document_preview.dart @@ -36,7 +36,10 @@ class DocumentPreview extends StatelessWidget { child: GestureDetector( behavior: HitTestBehavior.translucent, onTap: isClickable - ? () => DocumentPreviewRoute(id: documentId).push(context) + ? () => DocumentPreviewRoute( + id: documentId, + title: title, + ).push(context) : null, child: Builder(builder: (context) { if (enableHero) { diff --git a/lib/features/documents/view/widgets/items/document_grid_item.dart b/lib/features/documents/view/widgets/items/document_grid_item.dart index 5def307c..b56557e7 100644 --- a/lib/features/documents/view/widgets/items/document_grid_item.dart +++ b/lib/features/documents/view/widgets/items/document_grid_item.dart @@ -56,6 +56,7 @@ class DocumentGridItem extends DocumentItem { documentId: document.id, borderRadius: 12.0, enableHero: enableHeroAnimation, + title: document.title, ), ), Align( diff --git a/lib/features/documents/view/widgets/items/document_list_item.dart b/lib/features/documents/view/widgets/items/document_list_item.dart index 25cc629c..8e3a38ae 100644 --- a/lib/features/documents/view/widgets/items/document_list_item.dart +++ b/lib/features/documents/view/widgets/items/document_list_item.dart @@ -91,6 +91,7 @@ class DocumentListItem extends DocumentItem { child: GestureDetector( child: DocumentPreview( documentId: document.id, + title: document.title, fit: BoxFit.cover, alignment: Alignment.topCenter, enableHero: enableHeroAnimation, diff --git a/pubspec.lock b/pubspec.lock index 85b55f77..616ca1c4 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -85,10 +85,10 @@ packages: dependency: "direct dev" description: name: bloc_test - sha256: af0de1a1e16a7536e95dcd7491e0a6d6078e11d2d691988e862280b74f5c7968 + sha256: "02f04270be5abae8df171143e61a0058a7acbce5dcac887612e89bb40cca4c33" url: "https://pub.dev" source: hosted - version: "9.1.4" + version: "9.1.5" boolean_selector: dependency: transitive description: @@ -333,10 +333,10 @@ packages: dependency: "direct main" description: name: device_info_plus - sha256: f52ab3b76b36ede4d135aab80194df8925b553686f0fa12226b4e2d658e45903 + sha256: "7035152271ff67b072a211152846e9f1259cf1be41e34cd3e0b5463d2d6b8419" url: "https://pub.dev" source: hosted - version: "8.2.2" + version: "9.1.0" device_info_plus_platform_interface: dependency: transitive description: @@ -402,6 +402,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.1" + extension: + dependency: transitive + description: + name: extension + sha256: be3a6b7f8adad2f6e2e8c63c895d19811fcf203e23466c6296267941d0ff4f24 + url: "https://pub.dev" + source: hosted + version: "0.6.0" fake_async: dependency: transitive description: @@ -430,10 +438,10 @@ packages: dependency: "direct main" description: name: file_picker - sha256: "9d6e95ec73abbd31ec54d0e0df8a961017e165aba1395e462e5b31ea0c165daf" + sha256: be325344c1f3070354a1d84a231a1ba75ea85d413774ec4bdf444c023342e030 url: "https://pub.dev" source: hosted - version: "5.3.1" + version: "5.5.0" fixnum: dependency: transitive description: @@ -633,14 +641,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.4" - flutter_pdfview: - dependency: "direct main" - description: - name: flutter_pdfview - sha256: a9055bf920c7095bf08c2781db431ba23577aa5da5a056a7152dc89a18fbec6f - url: "https://pub.dev" - source: hosted - version: "1.3.2" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -788,10 +788,10 @@ packages: dependency: "direct dev" description: name: go_router_builder - sha256: b004ed761578fd1326054ff9c97daaf7b94f109b24cad843ca8bd349a810f947 + sha256: a4820cf40c647d674aa9305cdac2eaa6d03a795bb8f6b30c0469939417f7c4d8 url: "https://pub.dev" source: hosted - version: "2.3.3" + version: "2.3.4" graphs: dependency: transitive description: @@ -1219,6 +1219,15 @@ packages: url: "https://pub.dev" source: hosted version: "3.10.4" + pdfx: + dependency: "direct main" + description: + path: "packages/pdfx" + ref: HEAD + resolved-ref: "11f7dee82b58ca4f483c753f06bbdc91b34a0793" + url: "https://github.com/ScerIO/packages.flutter" + source: git + version: "2.5.0" permission_handler: dependency: "direct main" description: @@ -1600,6 +1609,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.0" + sprintf: + dependency: transitive + description: + name: sprintf + sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" + url: "https://pub.dev" + source: hosted + version: "7.0.0" sqflite: dependency: transitive description: @@ -1744,6 +1761,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.2" + universal_platform: + dependency: transitive + description: + name: universal_platform + sha256: d315be0f6641898b280ffa34e2ddb14f3d12b1a37882557869646e0cc363d0cc + url: "https://pub.dev" + source: hosted + version: "1.0.0+1" url_launcher: dependency: "direct main" description: @@ -1812,10 +1837,10 @@ packages: dependency: "direct main" description: name: uuid - sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" + sha256: b715b8d3858b6fa9f68f87d20d98830283628014750c2b09b6f516c1da4af2a7 url: "https://pub.dev" source: hosted - version: "3.0.7" + version: "4.1.0" vector_graphics: dependency: transitive description: @@ -1932,10 +1957,18 @@ packages: dependency: transitive description: name: win32 - sha256: "5a751eddf9db89b3e5f9d50c20ab8612296e4e8db69009788d6c8b060a84191c" + sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3" + url: "https://pub.dev" + source: hosted + version: "5.0.9" + win32_registry: + dependency: transitive + description: + name: win32_registry + sha256: "41fd8a189940d8696b1b810efb9abcf60827b6cbfab90b0c43e8439e3a39d85a" url: "https://pub.dev" source: hosted - version: "4.1.4" + version: "1.1.2" xdg_directories: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 15072747..881637c8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -59,7 +59,7 @@ dependencies: share_plus: ^4.5.3 introduction_screen: ^3.0.2 receive_sharing_intent: ^1.4.5 - uuid: ^3.0.6 + uuid: ^4.1.0 flutter_typeahead: ^4.3.3 fluttertoast: ^8.1.1 paperless_api: @@ -74,7 +74,7 @@ dependencies: json_annotation: ^4.8.1 pretty_dio_logger: ^1.2.0-beta-1 collection: ^1.17.0 - device_info_plus: ^8.0.0 + device_info_plus: ^9.0.3 flutter_local_notifications: ^13.0.0 responsive_builder: ^0.4.3 open_filex: ^4.3.2 @@ -88,7 +88,6 @@ dependencies: sliver_tools: ^0.2.10 webview_flutter: ^4.2.1 printing: ^5.11.0 - flutter_pdfview: ^1.3.1 go_router: ^10.0.0 fl_chart: ^0.63.0 palette_generator: ^0.3.3+2 @@ -102,6 +101,10 @@ dependencies: extended_masked_text: ^2.3.1 font_awesome_flutter: ^10.6.0 # camerawesome: ^2.0.0-dev.1 + pdfx: + git: + url: "https://github.com/ScerIO/packages.flutter" + path: packages/pdfx dependency_overrides: intl: ^0.18.1