diff --git a/lib/ui/app/buttons/elevated_button.dart b/lib/ui/app/buttons/elevated_button.dart index e7c9561a9..d9d88790f 100644 --- a/lib/ui/app/buttons/elevated_button.dart +++ b/lib/ui/app/buttons/elevated_button.dart @@ -34,7 +34,7 @@ class AppButton extends StatelessWidget { alignment: MainAxisAlignment.center, ) : Text(label, overflow: TextOverflow.ellipsis), - onPressed: () => onPressed(), + onPressed: onPressed, ); return Padding( diff --git a/lib/ui/invoice/edit/invoice_edit_desktop.dart b/lib/ui/invoice/edit/invoice_edit_desktop.dart index 520c58930..d8e26f846 100644 --- a/lib/ui/invoice/edit/invoice_edit_desktop.dart +++ b/lib/ui/invoice/edit/invoice_edit_desktop.dart @@ -6,9 +6,9 @@ import 'package:flutter_redux/flutter_redux.dart'; import 'package:invoiceninja_flutter/data/models/serializers.dart'; import 'package:invoiceninja_flutter/redux/app/app_state.dart'; import 'package:invoiceninja_flutter/ui/app/app_scrollbar.dart'; +import 'package:invoiceninja_flutter/ui/app/buttons/elevated_button.dart'; +import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; import 'package:native_pdf_view/native_pdf_view.dart'; -import 'package:invoiceninja_flutter/utils/web_stub.dart' - if (dart.library.html) 'package:invoiceninja_flutter/utils/web.dart'; import 'package:invoiceninja_flutter/constants.dart'; import 'package:invoiceninja_flutter/data/web_client.dart'; import 'package:invoiceninja_flutter/data/models/entities.dart'; @@ -28,7 +28,6 @@ import 'package:invoiceninja_flutter/ui/app/forms/discount_field.dart'; import 'package:invoiceninja_flutter/ui/app/forms/user_picker.dart'; import 'package:invoiceninja_flutter/ui/app/invoice/tax_rate_dropdown.dart'; import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart'; -import 'package:invoiceninja_flutter/ui/app/scrollable_listview.dart'; import 'package:invoiceninja_flutter/ui/credit/edit/credit_edit_items_vm.dart'; import 'package:invoiceninja_flutter/ui/invoice/edit/invoice_edit_contacts_vm.dart'; import 'package:invoiceninja_flutter/ui/invoice/edit/invoice_edit_details_vm.dart'; @@ -40,7 +39,6 @@ import 'package:invoiceninja_flutter/utils/completers.dart'; import 'package:invoiceninja_flutter/utils/formatting.dart'; import 'package:invoiceninja_flutter/utils/icons.dart'; import 'package:invoiceninja_flutter/utils/localization.dart'; -import 'package:pointer_interceptor/pointer_interceptor.dart'; class InvoiceEditDesktop extends StatefulWidget { const InvoiceEditDesktop({ @@ -846,8 +844,10 @@ class InvoiceEditDesktopState extends State ), ], ), - SizedBox(height: 20), - _PdfPreview(invoice: invoice), + Padding( + padding: const EdgeInsets.all(16), + child: _PdfPreview(invoice: invoice), + ), ], ), ), @@ -867,8 +867,9 @@ class _PdfPreview extends StatefulWidget { class __PdfPreviewState extends State<_PdfPreview> { final _pdfDebouncer = Debouncer(milliseconds: kMillisecondsToDebounceSave); + int _pageCount = 1; + int _currentPage = 1; bool _isLoading = false; - String _pdfString; PdfController _pdfController; @override @@ -895,7 +896,7 @@ class __PdfPreviewState extends State<_PdfPreview> { } void loadPdf() async { - if (_pdfController == null && _pdfString == null) { + if (_pdfController == null) { _loadPdf(); } else { _pdfDebouncer.run(() { @@ -935,14 +936,11 @@ class __PdfPreviewState extends State<_PdfPreview> { setState(() { _isLoading = false; - if (kIsWeb) { - _pdfString = - 'data:application/pdf;base64,' + base64Encode(response.bodyBytes); - WebUtils.registerWebView(_pdfString); - } else { - final document = PdfDocument.openData(response.bodyBytes); - _pdfController?.dispose(); + final document = PdfDocument.openData(response.bodyBytes); + if (_pdfController == null) { _pdfController = PdfController(document: document); + } else { + _pdfController.loadDocument(document); } }); }).catchError((dynamic error) { @@ -954,36 +952,78 @@ class __PdfPreviewState extends State<_PdfPreview> { @override Widget build(BuildContext context) { - if (_pdfString == null && _pdfController == null) { + final localization = AppLocalization.of(context); + + if (_pdfController == null) { return SizedBox(); } return Container( - height: 1200, + height: 1000, child: Stack( - alignment: Alignment.center, + alignment: Alignment.topCenter, children: [ - kIsWeb - ? Padding( - padding: const EdgeInsets.only(right: 11), - child: PointerInterceptor( - child: HtmlElementView(viewType: _pdfString), + Column( + children: [ + if (_pageCount > 1) + Padding( + padding: const EdgeInsets.only(bottom: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + AppButton( + label: localization.previousPage, + iconData: MdiIcons.pagePrevious, + onPressed: _currentPage == 1 + ? null + : () { + _pdfController.previousPage( + duration: Duration( + milliseconds: + kDefaultAnimationDuration), + curve: Curves.easeInOutCubic, + ); + }), + SizedBox(width: kTableColumnGap), + AppButton( + label: localization.nextPage, + iconData: MdiIcons.pageNext, + onPressed: _currentPage == _pageCount + ? null + : () { + _pdfController.nextPage( + duration: Duration( + milliseconds: + kDefaultAnimationDuration), + curve: Curves.easeInOutCubic, + ); + }), + ], ), - ) - : Padding( - padding: const EdgeInsets.all(8), - child: PdfView(controller: _pdfController), ), + Expanded( + child: PdfView( + controller: _pdfController, + //pageSnapping: false, + onDocumentLoaded: (document) { + setState(() { + _pageCount = document?.pagesCount ?? 0; + _currentPage = 1; + }); + }, + onPageChanged: (page) { + setState(() { + _currentPage = page; + }); + }, + ), + ), + ], + ), if (_isLoading) - Column( - mainAxisSize: MainAxisSize.max, - children: [ - LinearProgressIndicator(), - Expanded( - child: SizedBox(), - ), - ], - ), + Center( + child: CircularProgressIndicator(), + ) ], ), ); diff --git a/lib/utils/i18n.dart b/lib/utils/i18n.dart index 48b5bf57c..e1a8a2e6e 100644 --- a/lib/utils/i18n.dart +++ b/lib/utils/i18n.dart @@ -15,6 +15,8 @@ mixin LocalizationsProvider on LocaleCodeAware { static final Map> _localizedValues = { 'en': { // STARTER: lang key - do not remove comment + 'previous_page': 'Previous Page', + 'next_page': 'Next Page', 'export_colors': 'Export Colors', 'import_colors': 'Import Colors', 'default_clear_all': 'Default - Clear All', @@ -62441,6 +62443,14 @@ mixin LocalizationsProvider on LocaleCodeAware { _localizedValues[localeCode]['import_colors'] ?? _localizedValues['en']['import_colors']; + String get previousPage => + _localizedValues[localeCode]['previous_page'] ?? + _localizedValues['en']['previous_page']; + + String get nextPage => + _localizedValues[localeCode]['next_page'] ?? + _localizedValues['en']['next_page']; + String lookup(String key) { final lookupKey = toSnakeCase(key); diff --git a/web/index.html b/web/index.html index 2ed622506..07d173080 100644 --- a/web/index.html +++ b/web/index.html @@ -5,6 +5,10 @@ Invoice Ninja + +