diff --git a/contact/pubspec.lock b/contact/pubspec.lock index 3785f69db..c9ddc3944 100644 --- a/contact/pubspec.lock +++ b/contact/pubspec.lock @@ -820,26 +820,26 @@ packages: dependency: transitive description: name: path_provider - sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa + sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.5" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 + sha256: "4adf4fd5423ec60a29506c76581bc05854c55e3a0b72d35bb28d661c9686edf2" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.15" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" + sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.4.1" path_provider_linux: dependency: transitive description: @@ -900,10 +900,10 @@ packages: dependency: transitive description: name: plugin_platform_interface - sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" url: "https://pub.dev" source: hosted - version: "2.1.6" + version: "2.1.8" pointer_interceptor: dependency: transitive description: @@ -1138,26 +1138,26 @@ packages: dependency: transitive description: name: url_launcher - sha256: "75f2846facd11168d007529d6cd8fcb2b750186bea046af9711f10b907e1587e" + sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603" url: "https://pub.dev" source: hosted - version: "6.1.10" + version: "6.3.1" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "31222ffb0063171b526d3e569079cf1f8b294075ba323443fdc690842bfd4def" + sha256: "6fc2f56536ee873eeb867ad176ae15f304ccccc357848b351f6f0d8d4a40d193" url: "https://pub.dev" source: hosted - version: "6.2.0" + version: "6.3.14" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "4ac97281cf60e2e8c5cc703b2b28528f9b50c8f7cebc71df6bdf0845f647268a" + sha256: "16a513b6c12bb419304e72ea0ae2ab4fed569920d1c7cb850263fe3acc824626" url: "https://pub.dev" source: hosted - version: "6.2.0" + version: "6.3.2" url_launcher_linux: dependency: transitive description: @@ -1178,10 +1178,10 @@ packages: dependency: transitive description: name: url_launcher_platform_interface - sha256: "980e8d9af422f477be6948bdfb68df8433be71f5743a188968b0c1b887807e50" + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.2" url_launcher_web: dependency: transitive description: @@ -1303,5 +1303,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.4.0 <4.0.0" - flutter: ">=3.20.0-7.0.pre.48" + dart: ">=3.5.0 <4.0.0" + flutter: ">=3.24.0" diff --git a/core/pubspec.lock b/core/pubspec.lock index 14ffaf023..81b3cab43 100644 --- a/core/pubspec.lock +++ b/core/pubspec.lock @@ -781,26 +781,26 @@ packages: dependency: "direct main" description: name: path_provider - sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa + sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.5" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 + sha256: "4adf4fd5423ec60a29506c76581bc05854c55e3a0b72d35bb28d661c9686edf2" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.15" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" + sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.4.1" path_provider_linux: dependency: transitive description: @@ -1075,26 +1075,26 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: "75f2846facd11168d007529d6cd8fcb2b750186bea046af9711f10b907e1587e" + sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603" url: "https://pub.dev" source: hosted - version: "6.1.10" + version: "6.3.1" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "31222ffb0063171b526d3e569079cf1f8b294075ba323443fdc690842bfd4def" + sha256: "6fc2f56536ee873eeb867ad176ae15f304ccccc357848b351f6f0d8d4a40d193" url: "https://pub.dev" source: hosted - version: "6.2.0" + version: "6.3.14" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "4ac97281cf60e2e8c5cc703b2b28528f9b50c8f7cebc71df6bdf0845f647268a" + sha256: "16a513b6c12bb419304e72ea0ae2ab4fed569920d1c7cb850263fe3acc824626" url: "https://pub.dev" source: hosted - version: "6.2.0" + version: "6.3.2" url_launcher_linux: dependency: transitive description: @@ -1115,10 +1115,10 @@ packages: dependency: transitive description: name: url_launcher_platform_interface - sha256: "980e8d9af422f477be6948bdfb68df8433be71f5743a188968b0c1b887807e50" + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.2" url_launcher_web: dependency: transitive description: @@ -1240,5 +1240,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.4.0 <4.0.0" - flutter: ">=3.20.0-7.0.pre.48" + dart: ">=3.5.0 <4.0.0" + flutter: ">=3.24.0" diff --git a/core/pubspec.yaml b/core/pubspec.yaml index 2847842d4..01c916022 100644 --- a/core/pubspec.yaml +++ b/core/pubspec.yaml @@ -57,7 +57,7 @@ dependencies: flutter_inappwebview: 6.0.0 - url_launcher: 6.1.10 + url_launcher: 6.3.1 universal_html: 2.2.4 @@ -73,7 +73,7 @@ dependencies: http_parser: 4.0.2 - path_provider: 2.1.1 + path_provider: 2.1.5 collection: 1.18.0 diff --git a/lib/features/email/presentation/widgets/html_attachment_previewer.dart b/lib/features/email/presentation/widgets/html_attachment_previewer.dart index d8c17e874..b5d6391ac 100644 --- a/lib/features/email/presentation/widgets/html_attachment_previewer.dart +++ b/lib/features/email/presentation/widgets/html_attachment_previewer.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:core/presentation/utils/responsive_utils.dart'; import 'package:core/presentation/views/html_viewer/html_content_viewer_on_web_widget.dart'; import 'package:core/presentation/views/html_viewer/html_content_viewer_widget.dart'; @@ -9,6 +11,10 @@ import 'package:tmail_ui_user/features/base/isolate/background_isolate_binary_me import 'package:tmail_ui_user/features/email/presentation/widgets/pdf_viewer/top_bar_attachment_viewer.dart'; import 'package:tmail_ui_user/main/routes/route_navigation.dart'; import 'package:tmail_ui_user/main/utils/app_utils.dart'; +import 'package:twake_previewer_flutter/core/previewer_options/options/previewer_state.dart'; +import 'package:twake_previewer_flutter/core/previewer_options/previewer_options.dart'; +import 'package:twake_previewer_flutter/twake_html_previewer/options/html_view_options.dart'; +import 'package:twake_previewer_flutter/twake_html_previewer/twake_html_previewer.dart'; class HtmlAttachmentPreviewer extends StatefulWidget { const HtmlAttachmentPreviewer({ @@ -115,16 +121,22 @@ class _HtmlAttachmentPreviewerState extends State { required double height, }) { return PlatformInfo.isWeb - ? HtmlContentViewerOnWeb( - contentHtml: widget.htmlContent, - widthContent: width, - heightContent: height, - direction: AppUtils.getCurrentDirection(context), - mailtoDelegate: (uri) { - popBack(); - widget.mailToClicked(uri); - }, - keepWidthWhileLoading: true, + ? TwakeHtmlPreviewer( + bytes: utf8.encode(widget.htmlContent), + previewerOptions: PreviewerOptions( + previewerState: PreviewerState.success, + width: width, + height: height, + ), + htmlViewOptions: HtmlViewOptions( + contentClassName: 'tmail-content', + direction: AppUtils.getCurrentDirection(context), + mailtoDelegate: (uri) { + popBack(); + widget.mailToClicked(uri); + }, + keepWidthWhileLoading: true, + ), ) : HtmlContentViewer( contentHtml: widget.htmlContent, diff --git a/lib/features/email/presentation/widgets/pdf_viewer/pagination_pdf_viewer.dart b/lib/features/email/presentation/widgets/pdf_viewer/pagination_pdf_viewer.dart deleted file mode 100644 index 4c7afbef3..000000000 --- a/lib/features/email/presentation/widgets/pdf_viewer/pagination_pdf_viewer.dart +++ /dev/null @@ -1,226 +0,0 @@ -import 'package:core/utils/app_logger.dart'; -import 'package:flutter/material.dart'; -import 'package:pdf_render/pdf_render_widgets.dart'; -import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; - -enum ZoomState { - activate, - inactivate -} - -class PaginationPDFViewer extends StatefulWidget { - - final PdfViewerController? pdfViewerController; - - const PaginationPDFViewer({ - super.key, - this.pdfViewerController, - }); - - @override - State createState() => _PaginationPDFViewerState(); -} - -class _PaginationPDFViewerState extends State { - static const double _maxZoomLevelDefault = 4.0; - static const double _minZoomLevelDefault = 1.0; - - final ValueNotifier _zoomInPageNotifier = ValueNotifier(ZoomState.activate); - final ValueNotifier _zoomOutPageNotifier = ValueNotifier(ZoomState.inactivate); - final ValueNotifier _pageCurrentNotifier = ValueNotifier(1); - - double _zoomLevel = 1.0; - - @override - void initState() { - _zoomLevel = 1.0; - _pageCurrentNotifier.value = 1; - widget.pdfViewerController?.addListener(_pageChanged); - super.initState(); - } - - @override - void dispose() { - _zoomLevel = 1.0; - widget.pdfViewerController?.removeListener(_pageChanged); - _pageCurrentNotifier.dispose(); - _zoomInPageNotifier.dispose(); - _zoomOutPageNotifier.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Container( - decoration: BoxDecoration( - color: Colors.black.withOpacity(0.8), - borderRadius: const BorderRadius.all(Radius.circular(5)) - ), - height: 50, - padding: const EdgeInsetsDirectional.only(start: 16, end: 12), - margin: const EdgeInsets.only(bottom: 24), - child: Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - AppLocalizations.of(context).page, - style: Theme.of(context).textTheme.labelSmall?.copyWith( - color: Colors.white, - fontSize: 14 - ), - ), - const SizedBox(width: 12), - ValueListenableBuilder( - valueListenable: _pageCurrentNotifier, - builder: (_, value, __) { - return Text( - '$value', - style: Theme.of(context).textTheme.labelSmall?.copyWith( - color: Colors.white, - fontSize: 14 - ), - ); - }), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 8), - child: Text( - '/', - style: Theme.of(context).textTheme.labelSmall?.copyWith( - color: Colors.white, - fontSize: 14 - ), - ), - ), - Text( - '${widget.pdfViewerController?.pageCount}', - style: Theme.of(context).textTheme.labelSmall?.copyWith( - color: Colors.white, - fontSize: 14 - ), - ), - const Padding( - padding: EdgeInsetsDirectional.only(start: 12, end: 8), - child: VerticalDivider(color: Colors.grey), - ), - ValueListenableBuilder( - valueListenable: _zoomOutPageNotifier, - builder: (_, state, __) { - return IconButton( - onPressed: _zoomOutPage, - padding: const EdgeInsets.all(2), - icon: Icon( - Icons.horizontal_rule, - color: _getColorByZoomState(state), - size: 24, - ), - focusColor: Colors.black.withOpacity(0.3), - hoverColor: Colors.black.withOpacity(0.3), - tooltip: AppLocalizations.of(context).zoomOut, - ); - } - ), - const Padding( - padding: EdgeInsets.all(5), - child: Icon( - Icons.zoom_in, - color: Colors.white, - size: 28, - ), - ), - ValueListenableBuilder( - valueListenable: _zoomInPageNotifier, - builder: (_, state, __) { - return IconButton( - onPressed: _zoomInPage, - padding: const EdgeInsets.all(2), - icon: Icon( - Icons.add, - color: _getColorByZoomState(state), - size: 24, - ), - focusColor: Colors.black.withOpacity(0.3), - hoverColor: Colors.black.withOpacity(0.3), - tooltip: AppLocalizations.of(context).zoomIn, - ); - } - ) - ], - ), - ); - } - - Color _getColorByZoomState(ZoomState zoomState) { - switch (zoomState) { - case ZoomState.activate: - return Colors.white; - case ZoomState.inactivate: - return Colors.grey; - } - } - - void _pageChanged({String? property}) { - _pageCurrentNotifier.value = widget.pdfViewerController?.currentPageNumber ?? 1; - _updateZoomState(); - } - - void _zoomInPage() { - if (_zoomLevel < _maxZoomLevelDefault) { - if (_zoomLevel >= 1.0 && _zoomLevel < 1.25) { - _zoomLevel = 1.25; - } else if (_zoomLevel >= 1.25 && _zoomLevel < 1.50) { - _zoomLevel = 1.50; - } else if (_zoomLevel >= 1.50 && _zoomLevel < 2.0) { - _zoomLevel = 2.0; - } else if (_zoomLevel >= 2.0 && _zoomLevel < 2.50) { - _zoomLevel = 2.5; - } else if (_zoomLevel >= 2.5 && _zoomLevel < 3.0) { - _zoomLevel = 3.0; - } else if (_zoomLevel >= 3.0 && _zoomLevel < 3.5) { - _zoomLevel = 3.5; - } else if (_zoomLevel >= 3.5 && _zoomLevel < 4.0) { - _zoomLevel = 4.0; - } - _updateZoomState(); - widget.pdfViewerController?.setZoomRatio(zoomRatio: _zoomLevel); - } - } - - void _zoomOutPage() { - if (_zoomLevel > _minZoomLevelDefault) { - if (_zoomLevel > 1.0 && _zoomLevel <= 1.25) { - _zoomLevel = 1.0; - } else if (_zoomLevel > 1.25 && _zoomLevel <= 1.50) { - _zoomLevel = 1.25; - } else if (_zoomLevel > 1.50 && _zoomLevel <= 2.0) { - _zoomLevel = 1.50; - } else if (_zoomLevel > 2.0 && _zoomLevel <= 2.50) { - _zoomLevel = 2.0; - } else if (_zoomLevel > 2.5 && _zoomLevel <= 3.0) { - _zoomLevel = 2.5; - } else if (_zoomLevel > 3.0 && _zoomLevel <= 3.5) { - _zoomLevel = 3.0; - } else if (_zoomLevel > 3.5 && _zoomLevel <= 4.0) { - _zoomLevel = 3.5; - } - _updateZoomState(); - widget.pdfViewerController?.setZoomRatio(zoomRatio: _zoomLevel); - } - } - - void _updateZoomState() { - final zoomLevel = widget.pdfViewerController?.zoomRatio ?? 1.0; - log('_PaginationPDFViewerState::_updateZoomState:zoomLevel = $zoomLevel'); - if (zoomLevel <= _maxZoomLevelDefault && zoomLevel > _minZoomLevelDefault) { - _zoomOutPageNotifier.value = ZoomState.activate; - } else { - _zoomOutPageNotifier.value = ZoomState.inactivate; - } - - if (zoomLevel < _maxZoomLevelDefault && zoomLevel >= _minZoomLevelDefault) { - _zoomInPageNotifier.value = ZoomState.activate; - } else { - _zoomInPageNotifier.value = ZoomState.inactivate; - } - } -} diff --git a/lib/features/email/presentation/widgets/pdf_viewer/pdf_viewer.dart b/lib/features/email/presentation/widgets/pdf_viewer/pdf_viewer.dart index d7428da38..2145d0f6c 100644 --- a/lib/features/email/presentation/widgets/pdf_viewer/pdf_viewer.dart +++ b/lib/features/email/presentation/widgets/pdf_viewer/pdf_viewer.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:math'; import 'package:core/presentation/extensions/color_extension.dart'; import 'package:core/presentation/state/failure.dart'; @@ -14,16 +13,16 @@ import 'package:get/get.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:model/download/download_task_id.dart'; import 'package:model/email/attachment.dart'; -import 'package:pdf_render/pdf_render_widgets.dart'; -import 'package:percent_indicator/circular_percent_indicator.dart'; -import 'package:tmail_ui_user/features/base/widget/circle_loading_widget.dart'; import 'package:tmail_ui_user/features/email/domain/exceptions/download_attachment_exceptions.dart'; import 'package:tmail_ui_user/features/email/domain/state/download_attachment_for_web_state.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/download_attachment_for_web_interactor.dart'; -import 'package:tmail_ui_user/features/email/presentation/widgets/pdf_viewer/pagination_pdf_viewer.dart'; -import 'package:tmail_ui_user/features/email/presentation/widgets/pdf_viewer/top_bar_attachment_viewer.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/routes/route_navigation.dart'; +import 'package:twake_previewer_flutter/core/previewer_options/options/loading_options.dart'; +import 'package:twake_previewer_flutter/core/previewer_options/options/previewer_state.dart'; +import 'package:twake_previewer_flutter/core/previewer_options/options/top_bar_options.dart'; +import 'package:twake_previewer_flutter/core/previewer_options/previewer_options.dart'; +import 'package:twake_previewer_flutter/twake_pdf_previewer/twake_pdf_previewer.dart'; typedef DownloadPDFFileAction = Function(Uint8List bytes, String fileName); typedef PrintPDFFileAction = Function(Uint8List bytes, String fileName); @@ -56,11 +55,9 @@ class _PDFViewerState extends State { StreamSubscription>? _downloadInteractorStreamSubscription; CancelToken? _downloadAttachmentCancelToken; - final PdfViewerController _pdfViewerController = PdfViewerController(); final ValueNotifier _pdfViewStateNotifier = ValueNotifier(null); final DeviceInfoPlugin _deviceInfoPlugin = Get.find(); - final FocusNode _keyboardFocusNode = FocusNode(); @override void initState() { @@ -110,175 +107,85 @@ class _PDFViewerState extends State { @override void dispose() { - _pdfViewerController.dispose(); _pdfViewStateNotifier.dispose(); _downloadAttachmentStreamSubscription.cancel(); _downloadAttachmentStreamController.close(); _downloadInteractorStreamSubscription?.cancel(); _downloadInteractorStreamSubscription = null; _downloadAttachmentCancelToken = null; - _keyboardFocusNode.dispose(); super.dispose(); } @override Widget build(BuildContext context) { - return KeyboardListener( - focusNode: _keyboardFocusNode, - autofocus: true, - onKeyEvent: _handleKeyboardEventListener, - child: Center( - child: Stack( - children: [ - Center( - child: SizedBox( - width: double.infinity, - child: ValueListenableBuilder( - valueListenable: _pdfViewStateNotifier, - builder: (context, viewState, widget) { - if (viewState is DownloadAttachmentForWebSuccess) { - return PdfViewer.openData( - viewState.bytes, - viewerController: _pdfViewerController, - onError: (error) { - logError('_PDFViewerState::build:openData:onError:: $error'); - _pdfViewStateNotifier.value = DownloadAttachmentForWebFailure(exception: error); - }, - params: PdfViewerParams( - panAxis: PanAxis.vertical, - scrollByMouseWheel: 0.5, - layoutPages: (viewSize, pages) { - List rect = []; - final viewWidth = viewSize.width; - final viewHeight = viewSize.height; - final maxHeight = pages.fold(0.0, (maxHeight, page) => max(maxHeight, page.height)); - final maxWidth = pages.fold(0.0, (maxWidth, page) => max(maxWidth, page.width)); - final ratio = viewHeight / max(maxHeight, maxWidth); - log('_PDFViewerState::build: viewWidth = $viewWidth | viewHeight = $viewHeight | maxHeight = $maxHeight | ratio = $ratio'); - var top = 0.0; - double padding = 16.0; - for (var page in pages) { - final width = page.width * ratio; - final height = page.height * ratio; - final left = viewWidth > viewHeight ? (viewWidth / 2) - (width / 2) : 0.0; - rect.add(Rect.fromLTWH(left, top, width, height)); - top += height + padding; - } - return rect; - }, - onClickOutSidePageViewer: _closeView - ), - ); - } else if (viewState is DownloadingAttachmentForWeb) { - return CircularPercentIndicator( - percent: viewState.progress / 100, - progressColor: AppColor.primaryColor, - lineWidth: 4.0, - backgroundColor: Colors.white, - radius: 40, - center: Text( - '${viewState.progress.round()}%', - style: Theme.of(context).textTheme.labelMedium?.copyWith( - color: Colors.white, - fontSize: 17, - fontWeight: FontWeight.w500 - ), - ), - ); - } else if (viewState is DownloadAttachmentForWebFailure) { - return Center( - child: Text( - AppLocalizations.of(context).noPreviewAvailable, - style: Theme.of(context).textTheme.labelMedium?.copyWith( - color: Colors.white, - fontSize: 17, - fontWeight: FontWeight.w500 - ), - ), - ); - } else { - return const Center( - child: CircleLoadingWidget( - size: 80, - strokeWidth: 4.0, - ) - ); - } - }, - ) - ), - ), - Align( - alignment: AlignmentDirectional.topCenter, - child: ValueListenableBuilder( - valueListenable: _pdfViewStateNotifier, - builder: (context, viewState, child) { - if (viewState is DownloadAttachmentForWebSuccess) { - return FutureBuilder( - future: _deviceInfoPlugin.deviceInfo, - builder: (context, deviceInfo) { - BrowserName? browserName; - if (deviceInfo.hasData && deviceInfo.data is WebBrowserInfo) { - browserName = (deviceInfo.data as WebBrowserInfo).browserName; - } - return TopBarAttachmentViewer( - title: widget.attachment.generateFileName(), - downloadAction: () => widget.downloadAction?.call( - viewState.bytes, - widget.attachment.generateFileName() - ), - printAction: browserName != null && isBrowserSupportedPrinting(browserName) - ? () => widget.printAction?.call(viewState.bytes, widget.attachment.generateFileName()) - : null, - ); - }); - } - return child ?? const SizedBox.shrink(); + return FutureBuilder( + future: _deviceInfoPlugin.deviceInfo, + builder: (context, deviceInfo) { + BrowserName? browserName; + if (deviceInfo.hasData && deviceInfo.data is WebBrowserInfo) { + browserName = (deviceInfo.data as WebBrowserInfo).browserName; + } + + return ValueListenableBuilder( + valueListenable: _pdfViewStateNotifier, + builder: (context, viewState, child) { + final previewerState = switch (viewState) { + DownloadAttachmentForWebSuccess() => PreviewerState.success, + DownloadAttachmentForWebFailure() => PreviewerState.failure, + DownloadingAttachmentForWeb() => PreviewerState.loading, + _ => PreviewerState.idle, + }; + + final bytes = switch (viewState) { + DownloadAttachmentForWebSuccess(bytes: final bytes) => bytes, + _ => null, + }; + + final downloadProgress = switch (viewState) { + DownloadingAttachmentForWeb(progress: final progress) => progress / 100, + _ => 0.0, + }; + + final progressText = switch (viewState) { + DownloadingAttachmentForWeb(progress: final progress) => '${progress.round()}%', + _ => '', + }; + + final title = switch (viewState) { + DownloadAttachmentForWebSuccess(attachment: final attachment) => attachment.generateFileName(), + _ => '', + }; + + return TwakePdfPreviewer( + bytes: Uint8List.fromList(bytes ?? []), + previewerOptions: PreviewerOptions( + previewerState: previewerState, + onError: (error) { + logError('_PDFViewerState::build:openData:onError:: $error'); + _pdfViewStateNotifier.value = DownloadAttachmentForWebFailure(exception: error); }, - child: TopBarAttachmentViewer( - title: widget.attachment.generateFileName(), - closeAction: () { - _downloadAttachmentCancelToken?.cancel(); - Navigator.maybeOf(context)?.pop(); - }, - ), + errorMessage: AppLocalizations.of(context).noPreviewAvailable, ), - ), - ValueListenableBuilder( - valueListenable: _pdfViewerController, - builder: (_, __, ___) { - if (_pdfViewerController.isReady) { - return Align( - alignment: AlignmentDirectional.bottomCenter, - child: PaginationPDFViewer( - pdfViewerController: _pdfViewerController, - ), - ); - } else { - return const SizedBox.shrink(); - } - } - ), - ValueListenableBuilder( - valueListenable: _pdfViewerController, - builder: (context, m, child) { - if (!_pdfViewerController.isReady) return Container(); - final v = _pdfViewerController.viewRect; - final all = _pdfViewerController.fullSize; - final top = v.top / all.height * v.height; - final height = v.height / all.height * v.height; - return Positioned( - right: 0, - top: top, - height: height, - width: 8, - child: Container(color: AppColor.colorTextBody), - ); - }, - ), - ], - ), - ), + loadingOptions: LoadingOptions( + progress: downloadProgress, + progressColor: AppColor.primaryColor, + text: progressText, + ), + onTapOutside: _closeView, + topBarOptions: TopBarOptions( + title: title, + onDownload: bytes != null + ? () => widget.downloadAction?.call(bytes, title) + : null, + onPrint: browserName != null && isBrowserSupportedPrinting(browserName) && bytes != null + ? () => widget.printAction?.call(bytes, title) + : null, + onClose: _closeView, + ), + ); + }, + ); + } ); } @@ -286,10 +193,4 @@ class _PDFViewerState extends State { _downloadAttachmentCancelToken?.cancel(); Navigator.maybeOf(context)?.pop(); } - - void _handleKeyboardEventListener(KeyEvent event) { - if (event is KeyDownEvent && event.logicalKey == LogicalKeyboardKey.escape) { - _closeView(); - } - } } diff --git a/model/pubspec.lock b/model/pubspec.lock index 2e99dbff1..b45d5351c 100644 --- a/model/pubspec.lock +++ b/model/pubspec.lock @@ -797,26 +797,26 @@ packages: dependency: transitive description: name: path_provider - sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa + sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.5" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 + sha256: "4adf4fd5423ec60a29506c76581bc05854c55e3a0b72d35bb28d661c9686edf2" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.15" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" + sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.4.1" path_provider_linux: dependency: transitive description: @@ -877,10 +877,10 @@ packages: dependency: transitive description: name: plugin_platform_interface - sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" url: "https://pub.dev" source: hosted - version: "2.1.6" + version: "2.1.8" pointer_interceptor: dependency: transitive description: @@ -1115,26 +1115,26 @@ packages: dependency: transitive description: name: url_launcher - sha256: "75f2846facd11168d007529d6cd8fcb2b750186bea046af9711f10b907e1587e" + sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603" url: "https://pub.dev" source: hosted - version: "6.1.10" + version: "6.3.1" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "31222ffb0063171b526d3e569079cf1f8b294075ba323443fdc690842bfd4def" + sha256: "6fc2f56536ee873eeb867ad176ae15f304ccccc357848b351f6f0d8d4a40d193" url: "https://pub.dev" source: hosted - version: "6.2.0" + version: "6.3.14" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "4ac97281cf60e2e8c5cc703b2b28528f9b50c8f7cebc71df6bdf0845f647268a" + sha256: "16a513b6c12bb419304e72ea0ae2ab4fed569920d1c7cb850263fe3acc824626" url: "https://pub.dev" source: hosted - version: "6.2.0" + version: "6.3.2" url_launcher_linux: dependency: transitive description: @@ -1155,10 +1155,10 @@ packages: dependency: transitive description: name: url_launcher_platform_interface - sha256: "980e8d9af422f477be6948bdfb68df8433be71f5743a188968b0c1b887807e50" + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.2" url_launcher_web: dependency: transitive description: @@ -1280,5 +1280,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.4.0 <4.0.0" - flutter: ">=3.20.0-7.0.pre.48" + dart: ">=3.5.0 <4.0.0" + flutter: ">=3.24.0" diff --git a/pubspec.lock b/pubspec.lock index e141843b6..5638696c8 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -324,10 +324,10 @@ packages: dependency: transitive description: name: crypto - sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.6" csslib: dependency: transitive description: @@ -1244,10 +1244,10 @@ packages: dependency: transitive description: name: http - sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" + sha256: fe7ab022b76f3034adc518fb6ea04a82387620e19977665ea18d30a1cf43442f url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.3.0" http_mock_adapter: dependency: "direct dev" description: @@ -1525,26 +1525,26 @@ packages: dependency: "direct main" description: name: path_provider - sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa + sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.5" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 + sha256: "4adf4fd5423ec60a29506c76581bc05854c55e3a0b72d35bb28d661c9686edf2" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.15" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" + sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.4.1" path_provider_linux: dependency: transitive description: @@ -1609,15 +1609,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.10.8" - pdf_render: - dependency: "direct main" - description: - path: "." - ref: main - resolved-ref: "5ee423463cbeee302400d5e7fdae1a83c7fe1720" - url: "https://github.com/linagora/flutter_pdf_render.git" - source: git - version: "2.0.0" pdf_widget_wrapper: dependency: transitive description: @@ -1626,6 +1617,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.4" + pdfrx: + dependency: transitive + description: + name: pdfrx + sha256: "29c7b03d27d647c80da8cc08bd1256c74df90e5640fdd676646e4bd04f90553a" + url: "https://pub.dev" + source: hosted + version: "1.0.94" percent_indicator: dependency: "direct main" description: @@ -2040,6 +2039,14 @@ packages: url: "https://pub.dev" source: hosted version: "26.1.40" + synchronized: + dependency: transitive + description: + name: synchronized + sha256: "69fe30f3a8b04a0be0c15ae6490fc859a78ef4c43ae2dd5e8a623d45bfcf9225" + url: "https://pub.dev" + source: hosted + version: "3.3.0+3" term_glyph: dependency: transitive description: @@ -2088,6 +2095,15 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" + twake_previewer_flutter: + dependency: "direct main" + description: + path: "." + ref: main + resolved-ref: "79918fce64cfe7b7dd3d4b4555f4494e3fbb5639" + url: "https://github.com/linagora/twake-previewer-flutter.git" + source: git + version: "0.0.14" typed_data: dependency: transitive description: @@ -2124,26 +2140,26 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: "75f2846facd11168d007529d6cd8fcb2b750186bea046af9711f10b907e1587e" + sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603" url: "https://pub.dev" source: hosted - version: "6.1.10" + version: "6.3.1" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "31222ffb0063171b526d3e569079cf1f8b294075ba323443fdc690842bfd4def" + sha256: "6fc2f56536ee873eeb867ad176ae15f304ccccc357848b351f6f0d8d4a40d193" url: "https://pub.dev" source: hosted - version: "6.2.0" + version: "6.3.14" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "4ac97281cf60e2e8c5cc703b2b28528f9b50c8f7cebc71df6bdf0845f647268a" + sha256: "16a513b6c12bb419304e72ea0ae2ab4fed569920d1c7cb850263fe3acc824626" url: "https://pub.dev" source: hosted - version: "6.2.0" + version: "6.3.2" url_launcher_linux: dependency: transitive description: @@ -2164,10 +2180,10 @@ packages: dependency: transitive description: name: url_launcher_platform_interface - sha256: "980e8d9af422f477be6948bdfb68df8433be71f5743a188968b0c1b887807e50" + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.2" url_launcher_web: dependency: transitive description: @@ -2337,5 +2353,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.5.0 <4.0.0" + dart: ">=3.5.4 <4.0.0" flutter: ">=3.24.0" diff --git a/pubspec.yaml b/pubspec.yaml index 9d33a4a20..14c4f456f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -94,13 +94,6 @@ dependencies: url: https://github.com/linagora/dns_client.git ref: twake-supported - # TODO: We will change it when the PR in upstream repository will be merged - # https://github.com/espresso3389/flutter_pdf_render/pull/148 - pdf_render: - git: - url: https://github.com/linagora/flutter_pdf_render.git - ref: main - linagora_design_flutter: git: url: https://github.com/linagora/linagora-design-flutter.git @@ -150,7 +143,7 @@ dependencies: external_path: 1.0.3 - path_provider: 2.1.1 + path_provider: 2.1.5 device_info_plus: 9.0.1 @@ -192,7 +185,7 @@ dependencies: json_annotation: 4.8.0 - url_launcher: 6.1.10 + url_launcher: 6.3.1 firebase_core: 2.7.0 @@ -264,6 +257,11 @@ dependencies: flutter_file_dialog: 3.0.2 + twake_previewer_flutter: + git: + url: https://github.com/linagora/twake-previewer-flutter.git + ref: main + dev_dependencies: flutter_test: sdk: flutter diff --git a/web/index.html b/web/index.html index e5db5e484..855211419 100644 --- a/web/index.html +++ b/web/index.html @@ -84,18 +84,6 @@ - - -