From 8bbef91103de3cc773cf3879018be1b4cf604b84 Mon Sep 17 00:00:00 2001 From: Aman Raj Singh Mourya Date: Fri, 26 Jul 2024 18:02:17 +0530 Subject: [PATCH] [mob][photos] Add preview to the album link --- .../lib/ui/sharing/manage_links_widget.dart | 62 +++++++++++++++++- .../lib/ui/sharing/share_collection_page.dart | 64 ++++++++++++++++++- .../gallery/gallery_app_bar_widget.dart | 2 +- 3 files changed, 123 insertions(+), 5 deletions(-) diff --git a/mobile/lib/ui/sharing/manage_links_widget.dart b/mobile/lib/ui/sharing/manage_links_widget.dart index 3478d1864f..d0d71865b8 100644 --- a/mobile/lib/ui/sharing/manage_links_widget.dart +++ b/mobile/lib/ui/sharing/manage_links_widget.dart @@ -4,9 +4,12 @@ import 'package:collection/collection.dart'; import "package:fast_base58/fast_base58.dart"; import 'package:flutter/material.dart'; import "package:flutter/services.dart"; +import "package:photos/core/constants.dart"; +import "package:photos/db/files_db.dart"; import "package:photos/generated/l10n.dart"; import "package:photos/models/api/collection/public_url.dart"; import 'package:photos/models/collection/collection.dart'; +import "package:photos/models/file/file.dart"; import 'package:photos/services/collections_service.dart'; import 'package:photos/theme/colors.dart'; import 'package:photos/theme/ente_theme.dart'; @@ -18,17 +21,19 @@ import 'package:photos/ui/components/menu_section_description_widget.dart'; import "package:photos/ui/components/toggle_switch_widget.dart"; import 'package:photos/ui/sharing/pickers/device_limit_picker_page.dart'; import 'package:photos/ui/sharing/pickers/link_expiry_picker_page.dart'; +import "package:photos/ui/sharing/show_images_prevew.dart"; import 'package:photos/utils/crypto_util.dart'; import 'package:photos/utils/date_time_util.dart'; import 'package:photos/utils/dialog_util.dart'; import 'package:photos/utils/navigation_util.dart'; import "package:photos/utils/share_util.dart"; import 'package:photos/utils/toast_util.dart'; +import "package:screenshot/screenshot.dart"; class ManageSharedLinkWidget extends StatefulWidget { final Collection? collection; - const ManageSharedLinkWidget({Key? key, this.collection}) : super(key: key); + const ManageSharedLinkWidget({super.key, this.collection}); @override State createState() => _ManageSharedLinkWidgetState(); @@ -37,6 +42,8 @@ class ManageSharedLinkWidget extends StatefulWidget { class _ManageSharedLinkWidgetState extends State { final CollectionActions sharingActions = CollectionActions(CollectionsService.instance); + final ScreenshotController screenshotController = ScreenshotController(); + final GlobalKey sendLinkButtonKey = GlobalKey(); @override void initState() { @@ -271,6 +278,7 @@ class _ManageSharedLinkWidgetState extends State { ), if (!url.isExpired) MenuItemWidget( + key: sendLinkButtonKey, captionedTextWidget: CaptionedTextWidget( title: S.of(context).sendLink, makeTextBold: true, @@ -279,7 +287,11 @@ class _ManageSharedLinkWidgetState extends State { menuItemColor: getEnteColorScheme(context).fillFaint, onTap: () async { // ignore: unawaited_futures - shareText(urlValue); + _shareAlbumLink( + context, + widget.collection!, + urlValue, + ); }, isTopBorderRadiusRemoved: true, ), @@ -318,6 +330,52 @@ class _ManageSharedLinkWidgetState extends State { ); } + Future _createAlbumPlaceholder( + List ownedSelectedFiles, + ) async { + final Widget imageWidget = LinkPlaceholder( + files: ownedSelectedFiles, + ); + final double pixelRatio = MediaQuery.devicePixelRatioOf(context); + final bytesOfImageToWidget = await screenshotController.captureFromWidget( + imageWidget, + pixelRatio: pixelRatio, + targetSize: MediaQuery.sizeOf(context), + delay: const Duration(milliseconds: 300), + ); + return bytesOfImageToWidget; + } + + Future _shareAlbumLink( + BuildContext context, + Collection collection, + String url, + ) async { + final dialog = createProgressDialog( + context, + S.of(context).creatingLink, + isDismissible: true, + ); + await dialog.show(); + final List filesInCollection = + (await FilesDB.instance.getFilesInCollection( + collection.id, + galleryLoadStartTime, + galleryLoadEndTime, + )) + .files; + + final placeholderBytes = await _createAlbumPlaceholder(filesInCollection); + await dialog.hide(); + + await shareImageAndUrl( + placeholderBytes, + url, + context: context, + key: sendLinkButtonKey, + ); + } + Future> _getEncryptedPassword(String pass) async { final kekSalt = CryptoUtil.getSaltToDeriveKey(); final result = await CryptoUtil.deriveInteractiveKey( diff --git a/mobile/lib/ui/sharing/share_collection_page.dart b/mobile/lib/ui/sharing/share_collection_page.dart index 24e701159c..aef8acf3f2 100644 --- a/mobile/lib/ui/sharing/share_collection_page.dart +++ b/mobile/lib/ui/sharing/share_collection_page.dart @@ -2,9 +2,12 @@ import 'package:collection/collection.dart'; import 'package:fast_base58/fast_base58.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import "package:photos/core/constants.dart"; +import "package:photos/db/files_db.dart"; import "package:photos/generated/l10n.dart"; import "package:photos/models/api/collection/user.dart"; import 'package:photos/models/collection/collection.dart'; +import "package:photos/models/file/file.dart"; import 'package:photos/services/collections_service.dart'; import 'package:photos/theme/ente_theme.dart'; import 'package:photos/ui/actions/collection/collection_sharing_actions.dart'; @@ -18,15 +21,18 @@ import 'package:photos/ui/sharing/album_participants_page.dart'; import "package:photos/ui/sharing/album_share_info_widget.dart"; import "package:photos/ui/sharing/manage_album_participant.dart"; import 'package:photos/ui/sharing/manage_links_widget.dart'; +import "package:photos/ui/sharing/show_images_prevew.dart"; import 'package:photos/ui/sharing/user_avator_widget.dart'; +import "package:photos/utils/dialog_util.dart"; import 'package:photos/utils/navigation_util.dart'; import 'package:photos/utils/share_util.dart'; import 'package:photos/utils/toast_util.dart'; +import "package:screenshot/screenshot.dart"; class ShareCollectionPage extends StatefulWidget { final Collection collection; - const ShareCollectionPage(this.collection, {Key? key}) : super(key: key); + const ShareCollectionPage(this.collection, {super.key}); @override State createState() => _ShareCollectionPageState(); @@ -36,6 +42,55 @@ class _ShareCollectionPageState extends State { late List _sharees; final CollectionActions collectionActions = CollectionActions(CollectionsService.instance); + final ScreenshotController screenshotController = ScreenshotController(); + final GlobalKey sendLinkButtonKey = GlobalKey(); + + Future _createAlbumPlaceholder( + List ownedSelectedFiles, + ) async { + final Widget imageWidget = LinkPlaceholder( + files: ownedSelectedFiles, + ); + final double pixelRatio = MediaQuery.devicePixelRatioOf(context); + final bytesOfImageToWidget = await screenshotController.captureFromWidget( + imageWidget, + pixelRatio: pixelRatio, + targetSize: MediaQuery.sizeOf(context), + delay: const Duration(milliseconds: 300), + ); + return bytesOfImageToWidget; + } + + Future _shareAlbumLink( + BuildContext context, + Collection collection, + String url, + ) async { + final dialog = createProgressDialog( + context, + S.of(context).creatingLink, + isDismissible: true, + ); + await dialog.show(); + + final List filesInCollection = + (await FilesDB.instance.getFilesInCollection( + collection.id, + galleryLoadStartTime, + galleryLoadEndTime, + )) + .files; + + final placeholderBytes = await _createAlbumPlaceholder(filesInCollection); + await dialog.hide(); + + await shareImageAndUrl( + placeholderBytes, + url, + context: context, + key: sendLinkButtonKey, + ); + } Future _navigateToManageUser() async { if (_sharees.length == 1) { @@ -186,6 +241,7 @@ class _ShareCollectionPageState extends State { bgColor: getEnteColorScheme(context).fillFaint, ), MenuItemWidget( + key: sendLinkButtonKey, captionedTextWidget: CaptionedTextWidget( title: S.of(context).sendLink, makeTextBold: true, @@ -194,7 +250,11 @@ class _ShareCollectionPageState extends State { menuItemColor: getEnteColorScheme(context).fillFaint, onTap: () async { // ignore: unawaited_futures - shareText(url); + _shareAlbumLink( + context, + widget.collection, + url, + ); }, isTopBorderRadiusRemoved: true, isBottomBorderRadiusRemoved: true, diff --git a/mobile/lib/ui/viewer/gallery/gallery_app_bar_widget.dart b/mobile/lib/ui/viewer/gallery/gallery_app_bar_widget.dart index 5edd31984a..4535ce7c86 100644 --- a/mobile/lib/ui/viewer/gallery/gallery_app_bar_widget.dart +++ b/mobile/lib/ui/viewer/gallery/gallery_app_bar_widget.dart @@ -314,7 +314,7 @@ class _GalleryAppBarWidgetState extends State { icon: Icon( isQuickLink && (widget.collection!.hasLink) ? Icons.link_outlined - : Icons.people_outlined, + : Icons.adaptive.share, ), onPressed: () async { await _showShareCollectionDialog();