From b5eae21ae77b0a8dc4d88b70e8727e81f8a2193e Mon Sep 17 00:00:00 2001 From: Aman Raj Singh Mourya Date: Wed, 29 May 2024 13:02:45 +0530 Subject: [PATCH] [mob][photos] send placeholder with link when sharing --- mobile/lib/ui/TEMP/captureImage.dart | 65 -- mobile/lib/ui/TEMP/show_images_prevew.dart | 790 ------------------ mobile/lib/ui/TEMP/widget_to_image.dart | 19 - mobile/lib/ui/sharing/show_images_prevew.dart | 293 +++++++ .../file_selection_actions_widget.dart | 59 +- mobile/pubspec.lock | 8 + mobile/pubspec.yaml | 3 +- 7 files changed, 339 insertions(+), 898 deletions(-) delete mode 100644 mobile/lib/ui/TEMP/captureImage.dart delete mode 100644 mobile/lib/ui/TEMP/show_images_prevew.dart delete mode 100644 mobile/lib/ui/TEMP/widget_to_image.dart create mode 100644 mobile/lib/ui/sharing/show_images_prevew.dart diff --git a/mobile/lib/ui/TEMP/captureImage.dart b/mobile/lib/ui/TEMP/captureImage.dart deleted file mode 100644 index 65aec5a6ad..0000000000 --- a/mobile/lib/ui/TEMP/captureImage.dart +++ /dev/null @@ -1,65 +0,0 @@ -// import "dart:typed_data"; -// import 'dart:ui' as ui; - -// import 'package:flutter/material.dart'; -// import 'package:flutter/rendering.dart'; - -// class Captures { -// static Future capture(GlobalKey key) async { -// final double pixelRatio = -// MediaQuery.of(key.currentContext!).devicePixelRatio; -// final RenderRepaintBoundary boundary = -// key.currentContext!.findRenderObject()! as RenderRepaintBoundary; -// final ui.Image image = await boundary.toImage(pixelRatio: pixelRatio); -// final ByteData? byteData = -// await image.toByteData(format: ui.ImageByteFormat.png); -// final Uint8List pngBytes = byteData!.buffer.asUint8List(); -// print("PNG BYTES ====== ${pngBytes}"); -// return pngBytes; -// } -// } -import "dart:io"; -import 'dart:typed_data'; -import 'dart:ui' as ui; -import 'package:flutter/material.dart'; -import 'package:flutter/rendering.dart'; -import "package:path_provider/path_provider.dart"; - -class Captures { - Future capture(GlobalKey key) async { - try { - final double pixelRatio = - MediaQuery.of(key.currentContext!).devicePixelRatio; - final RenderRepaintBoundary boundary = - key.currentContext!.findRenderObject()! as RenderRepaintBoundary; - final ui.Image image = await boundary.toImage(pixelRatio: pixelRatio); - final ByteData? byteData = - await image.toByteData(format: ui.ImageByteFormat.png); - final Uint8List pngBytes = byteData!.buffer.asUint8List(); - print("PNG BYTES ====== ${pngBytes}"); - - return pngBytes; - } catch (e) { - print(e); - } - return null; - } - - Future saveImage(GlobalKey key) async { - String path = ""; - try { - final Uint8List? bytes = await capture(key); - final Directory root = await getTemporaryDirectory(); - final String directoryPath = '${root.path}/enteTempFiles'; - // Create the directory if it doesn't exist - final DateTime timeStamp = DateTime.now(); - await Directory(directoryPath).create(recursive: true); - final String filePath = '$directoryPath/$timeStamp.jpg'; - final file = await File(filePath).writeAsBytes(bytes!); - path = file.path; - } catch (e) { - debugPrint(e.toString()); - } - return path; - } -} diff --git a/mobile/lib/ui/TEMP/show_images_prevew.dart b/mobile/lib/ui/TEMP/show_images_prevew.dart deleted file mode 100644 index 90bdc78c2e..0000000000 --- a/mobile/lib/ui/TEMP/show_images_prevew.dart +++ /dev/null @@ -1,790 +0,0 @@ -import "dart:ui"; - -import "package:figma_squircle/figma_squircle.dart"; -import "package:flutter/material.dart"; -import "package:photos/models/file/file.dart"; -import "package:photos/ui/TEMP/captureImage.dart"; -import "package:photos/ui/TEMP/widget_to_image.dart"; -import "package:photos/ui/viewer/file/thumbnail_widget.dart"; - -class ShowImagePreviewFromTap extends StatefulWidget { - const ShowImagePreviewFromTap({ - required this.tempEnteFile, - super.key, - }); - final List tempEnteFile; - @override - State createState() => - _ShowImagePreviewFromTapState(); -} - -class _ShowImagePreviewFromTapState extends State { - // late String tempImagePath; - // final ValueNotifier bytesNotifier = - // ValueNotifier(null); - - late GlobalKey _widgetImageKey; - final ValueNotifier tempImagePath = ValueNotifier(null); - @override - void initState() { - super.initState(); - WidgetsBinding.instance.addPostFrameCallback((_) async { - //delay of 1 second before capturing the image - await Future.delayed(const Duration(milliseconds: 100)); - - tempImagePath.value = await Captures().saveImage(_widgetImageKey); - - Navigator.of(context).pop(tempImagePath.value); - }); - } - - @override - Widget build(BuildContext context) { - final int length = widget.tempEnteFile.length; - Widget placeholderWidget = const SizedBox( - height: 250, - width: 250, - ); - - if (length == 1) { - placeholderWidget = BackDrop( - backDropImage: widget.tempEnteFile[0], - children: [ - Padding( - padding: const EdgeInsets.all(18.0), - child: ClipSmoothRect( - radius: SmoothBorderRadius( - cornerRadius: 7.5, - cornerSmoothing: 1, - ), - child: ThumbnailWidget( - widget.tempEnteFile[0], - shouldShowArchiveStatus: false, - shouldShowSyncStatus: false, - ), - ), - ), - ], - ); - } else if (length == 2) { - placeholderWidget = BackDrop( - backDropImage: widget.tempEnteFile[0], - children: [ - Positioned( - top: 65, - left: 90, - child: CustomImage( - height: 100, - width: 100, - collages: widget.tempEnteFile[0], - zIndex: 0.2, - ), - ), - Positioned( - top: 20, - left: 0, - child: CustomImage( - height: 100, - width: 100, - collages: widget.tempEnteFile[1], - zIndex: -0.2, - ), - ), - ], - ); - } else if (length == 3) { - placeholderWidget = BackDrop( - backDropImage: widget.tempEnteFile[0], - children: [ - Positioned( - top: 30, - left: 0, - child: CustomImage( - height: 80, - width: 80, - collages: widget.tempEnteFile[1], - zIndex: -0.4, - ), - ), - Positioned( - top: 80, - left: 110, - child: CustomImage( - height: 80, - width: 80, - collages: widget.tempEnteFile[2], - zIndex: 0.4, - ), - ), - Positioned( - top: 40, - left: 40, - child: CustomImage( - height: 100, - width: 100, - collages: widget.tempEnteFile[0], - zIndex: 0.0, - ), - ), - ], - ); - } else if (length > 3) { - placeholderWidget = BackDrop( - backDropImage: widget.tempEnteFile[0], - children: [ - Positioned( - top: 10, - left: 10, - child: CustomImage( - height: 80, - width: 80, - collages: widget.tempEnteFile[1], - zIndex: 0, - ), - ), - Positioned( - top: 95, - left: 30, - child: CustomImage( - height: 80, - width: 80, - collages: widget.tempEnteFile[2], - zIndex: 0, - ), - ), - Positioned( - top: 35, - left: 60, - child: CustomImage( - height: 100, - width: 100, - collages: widget.tempEnteFile[0], - zIndex: 0.0, - ), - ), - Positioned( - top: 15, - left: 140, - child: Container( - padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - ), - child: Text( - "+" "$length", - style: const TextStyle( - fontWeight: FontWeight.w600, - color: Colors.black, - ), - ), - ), - ), - ], - ); - } - return Offstage( - offstage: false, - child: Center( - child: Column( - children: [ - WidgetToImage( - builder: (key) { - _widgetImageKey = key; - return placeholderWidget; - }, - ), - ], - ), - ), - ); - } -} - -class BackDrop extends StatelessWidget { - const BackDrop({ - super.key, - required this.backDropImage, - required this.children, - }); - final List children; - final EnteFile backDropImage; - @override - Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.all(4.0), - height: 200, - width: 200, - child: Stack( - children: [ - ClipSmoothRect( - radius: SmoothBorderRadius( - cornerRadius: 7.5, - cornerSmoothing: 1, - ), - child: ThumbnailWidget( - backDropImage, - shouldShowArchiveStatus: false, - shouldShowSyncStatus: false, - ), - ), - BackdropFilter( - filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5), - child: Container( - color: Colors.transparent, - ), - ), - ...children, - ], - ), - ); - } -} - -class CustomImage extends StatelessWidget { - const CustomImage({ - required this.width, - required this.height, - super.key, - required this.collages, - required this.zIndex, - }); - final EnteFile collages; - final double zIndex; - final double height; - final double width; - @override - Widget build(BuildContext context) { - return Container( - transform: Matrix4.rotationZ(zIndex), - height: height, - width: width, - child: ClipSmoothRect( - radius: SmoothBorderRadius( - cornerRadius: 7.5, - cornerSmoothing: 1, - ), - clipBehavior: Clip.antiAliasWithSaveLayer, - child: ThumbnailWidget( - collages, - shouldShowArchiveStatus: false, - shouldShowSyncStatus: false, - ), - ), - ); - } -} - -// import "dart:ui"; - -// import "package:figma_squircle/figma_squircle.dart"; -// import "package:flutter/material.dart"; -// import "package:photos/models/file/file.dart"; -// import "package:photos/ui/TEMP/captureImage.dart"; -// import "package:photos/ui/TEMP/widget_to_image.dart"; -// import "package:photos/ui/viewer/file/thumbnail_widget.dart"; - -// class ShowImagePrev { -// late GlobalKey _widgetImageKey; -// final ValueNotifier tempImagePath = ValueNotifier(null); -// Future imageToWidgetFunction(List tempEnteFile) async { -// showImagePreviewFromTap(tempEnteFile); -// await Future.delayed(const Duration(milliseconds: 100)); -// tempImagePath.value = await Captures().saveImage(_widgetImageKey); - -// print("VALUE IS ==================${tempImagePath.value}"); -// if (tempImagePath.value != null) { -// return tempImagePath.value; -// } -// return null; -// } - -// Widget showImagePreviewFromTap(List tempEnteFile) { -// final int length = tempEnteFile.length; -// Widget placeholderWidget = const SizedBox( -// height: 250, -// width: 250, -// ); - -// if (length == 1) { -// placeholderWidget = BackDrop( -// backDropImage: tempEnteFile[0], -// children: [ -// Padding( -// padding: const EdgeInsets.all(18.0), -// child: ClipSmoothRect( -// radius: SmoothBorderRadius( -// cornerRadius: 7.5, -// cornerSmoothing: 1, -// ), -// child: ThumbnailWidget( -// tempEnteFile[0], -// shouldShowArchiveStatus: false, -// shouldShowSyncStatus: false, -// ), -// ), -// ), -// ], -// ); -// } else if (length == 2) { -// placeholderWidget = BackDrop( -// backDropImage: tempEnteFile[0], -// children: [ -// Positioned( -// top: 65, -// left: 90, -// child: CustomImage( -// height: 100, -// width: 100, -// collages: tempEnteFile[0], -// zIndex: 0.2, -// ), -// ), -// Positioned( -// top: 20, -// left: 0, -// child: CustomImage( -// height: 100, -// width: 100, -// collages: tempEnteFile[1], -// zIndex: -0.2, -// ), -// ), -// ], -// ); -// } else if (length == 3) { -// placeholderWidget = BackDrop( -// backDropImage: tempEnteFile[0], -// children: [ -// Positioned( -// top: 30, -// left: 0, -// child: CustomImage( -// height: 80, -// width: 80, -// collages: tempEnteFile[1], -// zIndex: -0.4, -// ), -// ), -// Positioned( -// top: 80, -// left: 110, -// child: CustomImage( -// height: 80, -// width: 80, -// collages: tempEnteFile[2], -// zIndex: 0.4, -// ), -// ), -// Positioned( -// top: 40, -// left: 40, -// child: CustomImage( -// height: 100, -// width: 100, -// collages: tempEnteFile[0], -// zIndex: 0.0, -// ), -// ), -// ], -// ); -// } else if (length > 3) { -// placeholderWidget = BackDrop( -// backDropImage: tempEnteFile[0], -// children: [ -// Positioned( -// top: 10, -// left: 10, -// child: CustomImage( -// height: 80, -// width: 80, -// collages: tempEnteFile[1], -// zIndex: 0, -// ), -// ), -// Positioned( -// top: 95, -// left: 30, -// child: CustomImage( -// height: 80, -// width: 80, -// collages: tempEnteFile[2], -// zIndex: 0, -// ), -// ), -// Positioned( -// top: 35, -// left: 60, -// child: CustomImage( -// height: 100, -// width: 100, -// collages: tempEnteFile[0], -// zIndex: 0.0, -// ), -// ), -// Positioned( -// top: 15, -// left: 140, -// child: Container( -// padding: const EdgeInsets.all(8), -// decoration: BoxDecoration( -// color: Colors.white, -// borderRadius: BorderRadius.circular(12), -// ), -// child: Text( -// "+ $length", -// style: const TextStyle( -// fontWeight: FontWeight.w600, -// color: Colors.black, -// ), -// ), -// ), -// ), -// ], -// ); -// } - -// return Center( -// child: WidgetToImage( -// builder: (key) { -// _widgetImageKey = key; -// return placeholderWidget; -// }, -// ), -// ); -// } -// } - -// class BackDrop extends StatelessWidget { -// const BackDrop({ -// super.key, -// required this.backDropImage, -// required this.children, -// }); -// final List children; -// final EnteFile backDropImage; - -// @override -// Widget build(BuildContext context) { -// return Container( -// padding: const EdgeInsets.all(4.0), -// height: 200, -// width: 200, -// child: Stack( -// children: [ -// ClipSmoothRect( -// radius: SmoothBorderRadius( -// cornerRadius: 7.5, -// cornerSmoothing: 1, -// ), -// child: ThumbnailWidget( -// backDropImage, -// shouldShowArchiveStatus: false, -// shouldShowSyncStatus: false, -// ), -// ), -// BackdropFilter( -// filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5), -// child: Container( -// color: Colors.transparent, -// ), -// ), -// ...children, -// ], -// ), -// ); -// } -// } - -// class CustomImage extends StatelessWidget { -// const CustomImage({ -// required this.width, -// required this.height, -// super.key, -// required this.collages, -// required this.zIndex, -// }); -// final EnteFile collages; -// final double zIndex; -// final double height; -// final double width; -// @override -// Widget build(BuildContext context) { -// return Container( -// transform: Matrix4.rotationZ(zIndex), -// height: height, -// width: width, -// child: ClipSmoothRect( -// radius: SmoothBorderRadius( -// cornerRadius: 7.5, -// cornerSmoothing: 1, -// ), -// clipBehavior: Clip.antiAliasWithSaveLayer, -// child: ThumbnailWidget( -// collages, -// shouldShowArchiveStatus: false, -// shouldShowSyncStatus: false, -// ), -// ), -// ); -// } -// } -// import "dart:ui"; - -// import "package:figma_squircle/figma_squircle.dart"; -// import "package:flutter/material.dart"; -// import "package:photos/models/file/file.dart"; -// import "package:photos/ui/TEMP/captureImage.dart"; -// import "package:photos/ui/TEMP/widget_to_image.dart"; -// import "package:photos/ui/viewer/file/thumbnail_widget.dart"; - -// class ShowImagePrev { -// late GlobalKey _widgetImageKey; -// final ValueNotifier tempImagePath = ValueNotifier(null); - -// ShowImagePrev() { -// _widgetImageKey = GlobalKey(); -// } - -// Future imageToWidgetFunction(List tempEnteFile) async { -// showImagePreviewFromTap(tempEnteFile); -// // Build the widget to ensure the GlobalKey is assigned correctly -// WidgetsBinding.instance.addPostFrameCallback((_) async { -// await Future.delayed(const Duration(milliseconds: 100)); -// tempImagePath.value = await Captures().saveImage(_widgetImageKey); -// print("VALUE IS ==================${tempImagePath.value}"); -// }); - -// return tempImagePath.value; -// } - -// Widget showImagePreviewFromTap(List tempEnteFile) { -// final int length = tempEnteFile.length; -// Widget placeholderWidget = const SizedBox( -// height: 250, -// width: 250, -// ); - -// if (length == 1) { -// placeholderWidget = BackDrop( -// backDropImage: tempEnteFile[0], -// children: [ -// Padding( -// padding: const EdgeInsets.all(18.0), -// child: ClipSmoothRect( -// radius: SmoothBorderRadius( -// cornerRadius: 7.5, -// cornerSmoothing: 1, -// ), -// child: ThumbnailWidget( -// tempEnteFile[0], -// shouldShowArchiveStatus: false, -// shouldShowSyncStatus: false, -// ), -// ), -// ), -// ], -// ); -// } else if (length == 2) { -// placeholderWidget = BackDrop( -// backDropImage: tempEnteFile[0], -// children: [ -// Positioned( -// top: 65, -// left: 90, -// child: CustomImage( -// height: 100, -// width: 100, -// collages: tempEnteFile[0], -// zIndex: 0.2, -// ), -// ), -// Positioned( -// top: 20, -// left: 0, -// child: CustomImage( -// height: 100, -// width: 100, -// collages: tempEnteFile[1], -// zIndex: -0.2, -// ), -// ), -// ], -// ); -// } else if (length == 3) { -// placeholderWidget = BackDrop( -// backDropImage: tempEnteFile[0], -// children: [ -// Positioned( -// top: 30, -// left: 0, -// child: CustomImage( -// height: 80, -// width: 80, -// collages: tempEnteFile[1], -// zIndex: -0.4, -// ), -// ), -// Positioned( -// top: 80, -// left: 110, -// child: CustomImage( -// height: 80, -// width: 80, -// collages: tempEnteFile[2], -// zIndex: 0.4, -// ), -// ), -// Positioned( -// top: 40, -// left: 40, -// child: CustomImage( -// height: 100, -// width: 100, -// collages: tempEnteFile[0], -// zIndex: 0.0, -// ), -// ), -// ], -// ); -// } else if (length > 3) { -// placeholderWidget = BackDrop( -// backDropImage: tempEnteFile[0], -// children: [ -// Positioned( -// top: 10, -// left: 10, -// child: CustomImage( -// height: 80, -// width: 80, -// collages: tempEnteFile[1], -// zIndex: 0, -// ), -// ), -// Positioned( -// top: 95, -// left: 30, -// child: CustomImage( -// height: 80, -// width: 80, -// collages: tempEnteFile[2], -// zIndex: 0, -// ), -// ), -// Positioned( -// top: 35, -// left: 60, -// child: CustomImage( -// height: 100, -// width: 100, -// collages: tempEnteFile[0], -// zIndex: 0.0, -// ), -// ), -// Positioned( -// top: 15, -// left: 140, -// child: Container( -// padding: const EdgeInsets.all(8), -// decoration: BoxDecoration( -// color: Colors.white, -// borderRadius: BorderRadius.circular(12), -// ), -// child: Text( -// "+ $length", -// style: const TextStyle( -// fontWeight: FontWeight.w600, -// color: Colors.black, -// ), -// ), -// ), -// ), -// ], -// ); -// } - -// return Center( -// child: WidgetToImage( -// builder: (key) { -// _widgetImageKey = key; -// return placeholderWidget; -// }, -// ), -// ); -// } -// } - -// class BackDrop extends StatelessWidget { -// const BackDrop({ -// super.key, -// required this.backDropImage, -// required this.children, -// }); -// final List children; -// final EnteFile backDropImage; - -// @override -// Widget build(BuildContext context) { -// return Container( -// padding: const EdgeInsets.all(4.0), -// height: 200, -// width: 200, -// child: Stack( -// children: [ -// ClipSmoothRect( -// radius: SmoothBorderRadius( -// cornerRadius: 7.5, -// cornerSmoothing: 1, -// ), -// child: ThumbnailWidget( -// backDropImage, -// shouldShowArchiveStatus: false, -// shouldShowSyncStatus: false, -// ), -// ), -// BackdropFilter( -// filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5), -// child: Container( -// color: Colors.transparent, -// ), -// ), -// ...children, -// ], -// ), -// ); -// } -// } - -// class CustomImage extends StatelessWidget { -// const CustomImage({ -// required this.width, -// required this.height, -// super.key, -// required this.collages, -// required this.zIndex, -// }); -// final EnteFile collages; -// final double zIndex; -// final double height; -// final double width; -// @override -// Widget build(BuildContext context) { -// return Container( -// transform: Matrix4.rotationZ(zIndex), -// height: height, -// width: width, -// child: ClipSmoothRect( -// radius: SmoothBorderRadius( -// cornerRadius: 7.5, -// cornerSmoothing: 1, -// ), -// clipBehavior: Clip.antiAliasWithSaveLayer, -// child: ThumbnailWidget( -// collages, -// shouldShowArchiveStatus: false, -// shouldShowSyncStatus: false, -// ), -// ), -// ); -// } -// } diff --git a/mobile/lib/ui/TEMP/widget_to_image.dart b/mobile/lib/ui/TEMP/widget_to_image.dart deleted file mode 100644 index b00818b0da..0000000000 --- a/mobile/lib/ui/TEMP/widget_to_image.dart +++ /dev/null @@ -1,19 +0,0 @@ -import "package:flutter/material.dart"; - -class WidgetToImage extends StatefulWidget { - const WidgetToImage({super.key, required this.builder}); - final Function(GlobalKey key) builder; - @override - State createState() => _WidgetToImageState(); -} - -class _WidgetToImageState extends State { - final globalKey = GlobalKey(); - @override - Widget build(BuildContext context) { - return RepaintBoundary( - key: globalKey, - child: widget.builder(globalKey), - ); - } -} diff --git a/mobile/lib/ui/sharing/show_images_prevew.dart b/mobile/lib/ui/sharing/show_images_prevew.dart new file mode 100644 index 0000000000..7b0632554a --- /dev/null +++ b/mobile/lib/ui/sharing/show_images_prevew.dart @@ -0,0 +1,293 @@ +import "dart:ui"; + +import "package:figma_squircle/figma_squircle.dart"; +import "package:flutter/material.dart"; +import "package:photos/models/file/file.dart"; +import "package:photos/ui/viewer/file/thumbnail_widget.dart"; + +class ShowImagePreviewFromTap extends StatelessWidget { + const ShowImagePreviewFromTap({ + required this.tempEnteFile, + super.key, + }); + + final List tempEnteFile; + + @override + Widget build(BuildContext context) { + final int length = tempEnteFile.length; + Widget placeholderWidget = const SizedBox( + height: 300, // Adjusted height + width: 300, // Adjusted width + ); + + if (length == 1) { + placeholderWidget = AspectRatio( + aspectRatio: 1, + child: BackDrop( + backDropImage: tempEnteFile[0], + children: [ + Padding( + padding: const EdgeInsets.all(18.0), + child: Container( + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular(20.0), // Increased border radius + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.5), + spreadRadius: 1, + blurRadius: 1, + offset: const Offset(1, 1), + ), + BoxShadow( + color: Colors.black.withOpacity(0.5), + spreadRadius: 1, + blurRadius: 1, + offset: const Offset(-1, -1), + ), + ], + ), + child: ClipSmoothRect( + radius: SmoothBorderRadius( + cornerRadius: 15, + cornerSmoothing: 1, + ), + child: ThumbnailWidget( + tempEnteFile[0], + shouldShowArchiveStatus: false, + shouldShowSyncStatus: false, + ), + ), + ), + ), + ], + ), + ); + } else if (length == 2) { + placeholderWidget = AspectRatio( + aspectRatio: 1, + child: BackDrop( + backDropImage: tempEnteFile[0], + children: [ + Positioned( + right: 20, + bottom: 50, + child: CustomImage( + height: 190, + width: 190, + collages: tempEnteFile[1], + zIndex: 0.2, + ), + ), + Positioned( + top: 50, + left: 20, + child: CustomImage( + height: 190, + width: 190, + collages: tempEnteFile[0], + zIndex: -0.2, + ), + ), + ], + ), + ); + } else if (length == 3) { + placeholderWidget = AspectRatio( + aspectRatio: 1, + child: BackDrop( + backDropImage: tempEnteFile[0], + children: [ + //left image + Positioned( + top: 55, + left: 10, + child: CustomImage( + height: 160, + width: 160, + collages: tempEnteFile[1], + zIndex: -0.3, + ), + ), + //right image + Positioned( + right: 10, + bottom: 50, + child: CustomImage( + height: 160, + width: 160, + collages: tempEnteFile[2], + zIndex: 0.3, + ), + ), + //center image + Positioned( + top: 100, + left: 100, + child: CustomImage( + height: 175, + width: 175, + collages: tempEnteFile[0], + zIndex: 0.0, + ), + ), + ], + ), + ); + } else if (length > 3) { + placeholderWidget = Padding( + padding: const EdgeInsets.all(8.0), + child: AspectRatio( + aspectRatio: 1, + child: BackDrop( + backDropImage: tempEnteFile[0], + children: [ + Positioned( + top: 20, + left: 20, + child: CustomImage( + height: 160, + width: 160, + collages: tempEnteFile[1], + zIndex: 0, + ), + ), + Positioned( + bottom: 15, + left: 40, + child: CustomImage( + height: 160, + width: 160, + collages: tempEnteFile[2], + zIndex: 0, + ), + ), + Positioned( + top: 75, + right: 30, + child: CustomImage( + height: 175, + width: 175, + collages: tempEnteFile[0], + zIndex: 0.0, + ), + ), + Positioned( + bottom: 30, + right: 40, + child: ClipSmoothRect( + radius: SmoothBorderRadius( + cornerRadius: 7.5, + cornerSmoothing: 1, + ), + child: Container( + color: Colors.white, + height: 50, + width: 50, + child: Center( + child: Text( + "+" "$length", + style: const TextStyle( + fontWeight: FontWeight.w600, + fontSize: 24, + color: Colors.black, + ), + ), + ), + ), + ), + ), + ], + ), + ), + ); + } + + return placeholderWidget; + } +} + +class BackDrop extends StatelessWidget { + const BackDrop({ + super.key, + required this.backDropImage, + required this.children, + }); + + final List children; + final EnteFile backDropImage; + + @override + Widget build(BuildContext context) { + return Stack( + children: [ + ThumbnailWidget( + backDropImage, + shouldShowArchiveStatus: false, + shouldShowSyncStatus: false, + ), + BackdropFilter( + filter: ImageFilter.blur(sigmaX: 12, sigmaY: 12), // Increased blur + child: Container( + color: Colors.transparent, + ), + ), + ...children, + ], + ); + } +} + +class CustomImage extends StatelessWidget { + const CustomImage({ + required this.width, + required this.height, + super.key, + required this.collages, + required this.zIndex, + }); + + final EnteFile collages; + final double zIndex; + final double height; + final double width; + + @override + Widget build(BuildContext context) { + return Container( + transform: Matrix4.rotationZ(zIndex), + height: height, + width: width, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20.0), // Increased border radius + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.5), + spreadRadius: 1, + blurRadius: 1, + offset: const Offset(1, 1), + ), + BoxShadow( + color: Colors.black.withOpacity(0.5), + spreadRadius: 1, + blurRadius: 1, + offset: const Offset(-1, -1), + ), + ], + ), + child: ClipSmoothRect( + radius: SmoothBorderRadius( + cornerRadius: 20.0, // Increased corner radius + cornerSmoothing: 1, + ), + clipBehavior: Clip.antiAliasWithSaveLayer, + child: ThumbnailWidget( + collages, + shouldShowArchiveStatus: false, + shouldShowSyncStatus: false, + ), + ), + ); + } +} diff --git a/mobile/lib/ui/viewer/actions/file_selection_actions_widget.dart b/mobile/lib/ui/viewer/actions/file_selection_actions_widget.dart index 6c17ededbc..a6ad143d28 100644 --- a/mobile/lib/ui/viewer/actions/file_selection_actions_widget.dart +++ b/mobile/lib/ui/viewer/actions/file_selection_actions_widget.dart @@ -1,4 +1,5 @@ import "dart:async"; +import "dart:io"; import 'package:fast_base58/fast_base58.dart'; import "package:flutter/cupertino.dart"; @@ -6,6 +7,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import "package:logging/logging.dart"; import "package:modal_bottom_sheet/modal_bottom_sheet.dart"; +import "package:path_provider/path_provider.dart"; import 'package:photos/core/configuration.dart'; import "package:photos/core/event_bus.dart"; import "package:photos/events/people_changed_event.dart"; @@ -25,7 +27,6 @@ import 'package:photos/services/machine_learning/face_ml/feedback/cluster_feedba import "package:photos/services/machine_learning/face_ml/person/person_service.dart"; import "package:photos/theme/colors.dart"; import "package:photos/theme/ente_theme.dart"; -import "package:photos/ui/TEMP/show_images_prevew.dart"; import 'package:photos/ui/actions/collection/collection_file_actions.dart'; import 'package:photos/ui/actions/collection/collection_sharing_actions.dart'; import 'package:photos/ui/collections/collection_action_sheet.dart'; @@ -34,6 +35,7 @@ import "package:photos/ui/components/bottom_action_bar/selection_action_button_w import 'package:photos/ui/components/buttons/button_widget.dart'; import 'package:photos/ui/components/models/button_type.dart'; import 'package:photos/ui/sharing/manage_links_widget.dart'; +import "package:photos/ui/sharing/show_images_prevew.dart"; import "package:photos/ui/tools/collage/collage_creator_page.dart"; import "package:photos/ui/viewer/location/update_location_data_widget.dart"; import 'package:photos/utils/delete_file_util.dart'; @@ -43,6 +45,7 @@ import 'package:photos/utils/magic_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 FileSelectionActionsWidget extends StatefulWidget { final GalleryType type; @@ -74,7 +77,7 @@ class _FileSelectionActionsWidgetState late FilesSplit split; late CollectionActions collectionActions; late bool isCollectionOwner; - + ScreenshotController screenshotController = ScreenshotController(); // _cachedCollectionForSharedLink is primarily used to avoid creating duplicate // links if user keeps on creating Create link button after selecting // few files. This link is reset on any selection changed; @@ -603,22 +606,39 @@ class _FileSelectionActionsWidgetState } } + Future saveImage(Uint8List bytes) async { + String path = ""; + try { + final Directory root = await getTemporaryDirectory(); + final String directoryPath = '${root.path}/enteTempFiles'; + // Create the directory if it doesn't exist + final DateTime timeStamp = DateTime.now(); + await Directory(directoryPath).create(recursive: true); + final String filePath = '$directoryPath/$timeStamp.jpg'; + final file = await File(filePath).writeAsBytes(bytes!); + path = file.path; + } catch (e) { + debugPrint(e.toString()); + } + return path; + } + ValueNotifier generatedPathNotifier = ValueNotifier(null); //Future function to go to next page Future _nextPageForTesting(List tempfile) async { - final String? tempImagePath = await Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => ShowImagePreviewFromTap( - tempEnteFile: tempfile, - ), - ), + final Widget imageWidget = ShowImagePreviewFromTap( + tempEnteFile: tempfile, + ); + await Future.delayed(const Duration(milliseconds: 100)); + final double pixelRatio = MediaQuery.of(context).devicePixelRatio; + final bytesOfImageToWidget = await screenshotController.captureFromWidget( + imageWidget, + pixelRatio: pixelRatio, + targetSize: MediaQuery.of(context).size, + delay: const Duration(milliseconds: 100), ); - if (tempImagePath != null) { - print("Temp image path: $tempImagePath"); - - return tempImagePath; - } + final String tempImagePath = await saveImage(bytesOfImageToWidget); return tempImagePath; } @@ -645,13 +665,6 @@ class _FileSelectionActionsWidgetState shouldStickToDarkTheme: true, buttonAction: ButtonAction.first, isInAlert: true, - // onTap: () async { - // // Add a return statement at the end of the function - // generatedPathNotifier.value = - // await _nextPageForTesting(tempEnteFile); - // await shareText(generatedPathNotifier.value!); - // return Future.value(); - // }, ), ButtonWidget( labelText: S.of(context).manageLink, @@ -676,7 +689,7 @@ class _FileSelectionActionsWidgetState ); if (actionResult?.action != null) { if (actionResult!.action == ButtonAction.first) { - //generatedPathNotifier.value = await _nextPageForTesting(tempEnteFile); + generatedPathNotifier.value = await _nextPageForTesting(tempEnteFile); await _copyLink(); } if (actionResult.action == ButtonAction.second) { @@ -796,8 +809,8 @@ class _FileSelectionActionsWidgetState ); final String url = "${_cachedCollectionForSharedLink!.publicURLs?.first?.url}#$collectionKey"; - await shareText(url); - //await shareImageAndUrl(context, generatedPathNotifier.value!, url); + //await shareText(url); + await shareImageAndUrl(context, generatedPathNotifier.value!, url); await Clipboard.setData(ClipboardData(text: url)); showShortToast(context, S.of(context).linkCopiedToClipboard); } diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index 1d1082bfd3..6d6d0621d8 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -1863,6 +1863,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.1.3" + screenshot: + dependency: "direct main" + description: + name: screenshot + sha256: d448f43130f49bc7eead1b267b3ea0291cb2450f037bb0a0ecce7aa4c65e2aee + url: "https://pub.dev" + source: hosted + version: "2.5.0" scrollable_positioned_list: dependency: "direct main" description: diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index 211d744ccc..f8d9c67c54 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -141,10 +141,11 @@ dependencies: provider: ^6.0.0 quiver: ^3.0.1 receive_sharing_intent: ^1.7.0 + screenshot: ^2.4.0 scrollable_positioned_list: ^0.3.5 sentry: ^7.9.0 sentry_flutter: ^7.9.0 - share_plus: 7.2.2 + share_plus: 7.2.2 shared_preferences: ^2.0.5 simple_cluster: ^0.3.0 sqflite: ^2.3.0