From edc9917b572cbff32e3c54a4bf48e031da19c06a Mon Sep 17 00:00:00 2001 From: AmanRajSinghMourya Date: Tue, 10 Jun 2025 12:09:51 +0530 Subject: [PATCH 1/8] Work around for swipe between memories --- mobile/ios/Podfile.lock | 118 +++++++-------- .../ui/home/memories/full_screen_memory.dart | 136 +++++++----------- .../lib/ui/home/memories/memories_widget.dart | 1 + .../ui/home/memories/memory_cover_widget.dart | 26 ++-- mobile/lib/ui/home/memories/temp.dart | 54 +++++++ .../notification/update/change_log_page.dart | 3 +- 6 files changed, 184 insertions(+), 154 deletions(-) create mode 100644 mobile/lib/ui/home/memories/temp.dart diff --git a/mobile/ios/Podfile.lock b/mobile/ios/Podfile.lock index 35f0ecafad..2183c80ea9 100644 --- a/mobile/ios/Podfile.lock +++ b/mobile/ios/Podfile.lock @@ -75,6 +75,8 @@ PODS: - Flutter - flutter_sodium (0.0.1): - Flutter + - flutter_timezone (0.0.1): + - Flutter - fluttertoast (0.0.2): - Flutter - GoogleDataTransport (10.1.0): @@ -259,6 +261,7 @@ DEPENDENCIES: - flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`) - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) - flutter_sodium (from `.symlinks/plugins/flutter_sodium/ios`) + - flutter_timezone (from `.symlinks/plugins/flutter_timezone/ios`) - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) - home_widget (from `.symlinks/plugins/home_widget/ios`) - image_editor_common (from `.symlinks/plugins/image_editor_common/ios`) @@ -298,7 +301,7 @@ DEPENDENCIES: - wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`) SPEC REPOS: - https://github.com/ente-io/ffmpeg-kit-custom-repo-ios: + https://github.com/ente-io/ffmpeg-kit-custom-repo-ios.git: - ffmpeg_kit_custom trunk: - Firebase @@ -359,6 +362,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/flutter_secure_storage/ios" flutter_sodium: :path: ".symlinks/plugins/flutter_sodium/ios" + flutter_timezone: + :path: ".symlinks/plugins/flutter_timezone/ios" fluttertoast: :path: ".symlinks/plugins/fluttertoast/ios" home_widget: @@ -435,81 +440,82 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/wakelock_plus/ios" SPEC CHECKSUMS: - app_links: f3e17e4ee5e357b39d8b95290a9b2c299fca71c6 - background_fetch: 39f11371c0dce04b001c4bfd5e782bcccb0a85e2 - battery_info: b6c551049266af31556b93c9d9b9452cfec0219f - connectivity_plus: 2a701ffec2c0ae28a48cf7540e279787e77c447d - cupertino_http: 947a233f40cfea55167a49f2facc18434ea117ba - dart_ui_isolate: d5bcda83ca4b04f129d70eb90110b7a567aece14 - device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6 + app_links: 76b66b60cc809390ca1ad69bfd66b998d2387ac7 + background_fetch: 94b36ee293e82972852dba8ede1fbcd3bd3d9d57 + battery_info: 83f3aae7be2fccefab1d2bf06b8aa96f11c8bcdd + connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd + cupertino_http: 94ac07f5ff090b8effa6c5e2c47871d48ab7c86c + dart_ui_isolate: 46f6714abe6891313267153ef6f9748d8ecfcab1 + device_info_plus: 335f3ce08d2e174b9fdc3db3db0f4e3b1f66bd89 ffmpeg_kit_custom: 682b4f2f1ff1f8abae5a92f6c3540f2441d5be99 - ffmpeg_kit_flutter: 9dce4803991478c78c6fb9f972703301101095fe - file_saver: 503e386464dbe118f630e17b4c2e1190fa0cf808 + ffmpeg_kit_flutter: 915b345acc97d4142e8a9a8549d177ff10f043f5 + file_saver: 6cdbcddd690cb02b0c1a0c225b37cd805c2bf8b6 Firebase: d80354ed7f6df5f9aca55e9eb47cc4b634735eaf - firebase_core: 6e223dfa350b2edceb729cea505eaaef59330682 - firebase_messaging: 07fde77ae28c08616a1d4d870450efc2b38cf40d + firebase_core: 6cbed78b4f298ed103a9fd034e6dbc846320480f + firebase_messaging: 5e0adf2eb18b0ee59aa0c109314c091a0497ecac FirebaseCore: 99fe0c4b44a39f37d99e6404e02009d2db5d718d FirebaseCoreInternal: df24ce5af28864660ecbd13596fc8dd3a8c34629 FirebaseInstallations: 6c963bd2a86aca0481eef4f48f5a4df783ae5917 FirebaseMessaging: 487b634ccdf6f7b7ff180fdcb2a9935490f764e8 Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 - flutter_email_sender: e03bdda7637bcd3539bfe718fddd980e9508efaa - flutter_image_compress_common: ec1d45c362c9d30a3f6a0426c297f47c52007e3e - flutter_inappwebview_ios: 6f63631e2c62a7c350263b13fa5427aedefe81d4 - flutter_local_notifications: 4cde75091f6327eb8517fa068a0a5950212d2086 - flutter_native_splash: f71420956eb811e6d310720fee915f1d42852e7a - flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be - flutter_sodium: a00383520fc689c688b66fd3092984174712493e - fluttertoast: 21eecd6935e7064cc1fcb733a4c5a428f3f24f0f + flutter_email_sender: aa1e9772696691d02cd91fea829856c11efb8e58 + flutter_image_compress_common: 1697a328fd72bfb335507c6bca1a65fa5ad87df1 + flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99 + flutter_local_notifications: ad39620c743ea4c15127860f4b5641649a988100 + flutter_native_splash: 6cad9122ea0fad137d23137dd14b937f3e90b145 + flutter_secure_storage: 2c2ff13db9e0a5647389bff88b0ecac56e3f3418 + flutter_sodium: 7e4621538491834eba53bd524547854bcbbd6987 + flutter_timezone: 7c838e17ffd4645d261e87037e5bebf6d38fe544 + fluttertoast: 2c67e14dce98bbdb200df9e1acf610d7a6264ea1 GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7 GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d - home_widget: 0434835a4c9a75704264feff6be17ea40e0f0d57 - image_editor_common: d6f6644ae4a6de80481e89fe6d0a8c49e30b4b43 - in_app_purchase_storekit: a1ce04056e23eecc666b086040239da7619cd783 - integration_test: 252f60fa39af5e17c3aa9899d35d908a0721b573 - launcher_icon_switcher: 8e0ad2131a20c51c1dd939896ee32e70cd845b37 + home_widget: f169fc41fd807b4d46ab6615dc44d62adbf9f64f + image_editor_common: 3de87e7c4804f4ae24c8f8a998362b98c105cac1 + in_app_purchase_storekit: d1a48cb0f8b29dbf5f85f782f5dd79b21b90a5e6 + integration_test: 4a889634ef21a45d28d50d622cf412dc6d9f586e + launcher_icon_switcher: 84c218d233505aa7d8655d8fa61a3ba802c022da libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8 - local_auth_darwin: 66e40372f1c29f383a314c738c7446e2f7fdadc3 - local_auth_ios: 5046a18c018dd973247a0564496c8898dbb5adf9 + local_auth_darwin: 553ce4f9b16d3fdfeafce9cf042e7c9f77c1c391 + local_auth_ios: f7a1841beef3151d140a967c2e46f30637cdf451 Mantle: c5aa8794a29a022dfbbfc9799af95f477a69b62d - maps_launcher: 2e5b6a2d664ec6c27f82ffa81b74228d770ab203 - media_extension: 6618f07abd762cdbfaadf1b0c56a287e820f0c84 - media_kit_libs_ios_video: a5fe24bc7875ccd6378a0978c13185e1344651c1 - media_kit_video: 5da63f157170e5bf303bf85453b7ef6971218a2e - motion_sensors: 03f55b7c637a7e365a0b5f9697a449f9059d5d91 - motionphoto: 8b65ce50c7d7ff3c767534fc3768b2eed9ac24e4 - move_to_background: cd3091014529ec7829e342ad2d75c0a11f4378a5 + maps_launcher: edf829809ba9e894d70e569bab11c16352dedb45 + media_extension: 671e2567880d96c95c65c9a82ccceed8f2e309fd + media_kit_libs_ios_video: 5a18affdb97d1f5d466dc79988b13eff6c5e2854 + media_kit_video: 1746e198cb697d1ffb734b1d05ec429d1fcd1474 + motion_sensors: 741e702c17467b9569a92165dda8d4d88c6167f1 + motionphoto: 23e2aeb5c6380112f69468d71f970fa7438e5ed1 + move_to_background: 7e3467dd2a1d1013e98c9c1cb93fd53cd7ef9d84 nanopb: fad817b59e0457d11a5dfbde799381cd727c1275 - native_video_player: 5d36066807b680e181473e6890dde643ac85380d - objective_c: 77e887b5ba1827970907e10e832eec1683f3431d - onnxruntime: e7c2ae44385191eaad5ae64c935a72debaddc997 + native_video_player: e363dd14f6a498ad8a8f7e6486a0db046ad19f13 + objective_c: 89e720c30d716b036faf9c9684022048eee1eee2 + onnxruntime: f9b296392c96c42882be020a59dbeac6310d81b2 onnxruntime-c: a909204639a1f035f575127ac406f781ac797c9c onnxruntime-objc: b6fab0f1787aa6f7190c2013f03037df4718bd8b - open_mail_app: 70273c53f768beefdafbe310c3d9086e4da3cb02 + open_mail_app: 7314a609e88eed22d53671279e189af7a0ab0f11 OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94 - package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4 - path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 - permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2 - photo_manager: ff695c7a1dd5bc379974953a2b5c0a293f7c4c8a - privacy_screen: 1a131c052ceb3c3659934b003b0d397c2381a24e + package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499 + path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564 + permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d + photo_manager: d2fbcc0f2d82458700ee6256a15018210a81d413 + privacy_screen: 3159a541f5d3a31bea916cfd4e58f9dc722b3fd4 PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 - receive_sharing_intent: 79c848f5b045674ad60b9fea3bafea59962ad2c1 + receive_sharing_intent: 222384f00ffe7e952bbfabaa9e3967cb87e5fe00 SDWebImage: f84b0feeb08d2d11e6a9b843cb06d75ebf5b8868 SDWebImageWebPCoder: e38c0a70396191361d60c092933e22c20d5b1380 Sentry: da60d980b197a46db0b35ea12cb8f39af48d8854 - sentry_flutter: 6a134f9d381e49f22ea25a67736cf0cf4d02ec9c - share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f - shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 - sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d + sentry_flutter: 942017adbe00f963061cb11ec260414a990b7a42 + share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a + shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7 + sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0 sqlite3: fc1400008a9b3525f5914ed715a5d1af0b8f4983 - sqlite3_flutter_libs: 069c435986dd4b63461aecd68f4b30be4a9e9daa - system_info_plus: 5393c8da281d899950d751713575fbf91c7709aa - ua_client_hints: aeabd123262c087f0ce151ef96fa3ab77bfc8b38 - url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe - video_player_avfoundation: 7c6c11d8470e1675df7397027218274b6d2360b3 - video_thumbnail: 94ba6705afbaa120b77287080424930f23ea0c40 - volume_controller: 2e3de73d6e7e81a0067310d17fb70f2f86d71ac7 - wakelock_plus: 373cfe59b235a6dd5837d0fb88791d2f13a90d56 + sqlite3_flutter_libs: 3c323550ef3b928bc0aa9513c841e45a7d242832 + system_info_plus: 555ce7047fbbf29154726db942ae785c29211740 + ua_client_hints: 92fe0d139619b73ec9fcb46cc7e079a26178f586 + url_launcher_ios: 694010445543906933d732453a59da0a173ae33d + video_player_avfoundation: 2cef49524dd1f16c5300b9cd6efd9611ce03639b + video_thumbnail: 584ccfa55d8fd2f3d5507218b0a18d84c839c620 + volume_controller: 3657a1f65bedb98fa41ff7dc5793537919f31b12 + wakelock_plus: 04623e3f525556020ebd4034310f20fe7fda8b49 PODFILE CHECKSUM: a8ef88ad74ba499756207e7592c6071a96756d18 diff --git a/mobile/lib/ui/home/memories/full_screen_memory.dart b/mobile/lib/ui/home/memories/full_screen_memory.dart index ecd34ac069..20c7bc8293 100644 --- a/mobile/lib/ui/home/memories/full_screen_memory.dart +++ b/mobile/lib/ui/home/memories/full_screen_memory.dart @@ -134,7 +134,6 @@ class FullScreenMemory extends StatefulWidget { } class _FullScreenMemoryState extends State { - PageController? _pageController; final _showTitle = ValueNotifier(true); AnimationController? _progressAnimationController; AnimationController? _zoomAnimationController; @@ -145,36 +144,24 @@ class _FullScreenMemoryState extends State { void initState() { super.initState(); Future.delayed(const Duration(seconds: 3), () { - if (mounted) { - setState(() { - _showTitle.value = false; - }); - } + if (mounted) _showTitle.value = false; }); } @override void dispose() { - _pageController?.dispose(); _showTitle.dispose(); durationNotifier.dispose(); super.dispose(); } void _toggleAnimation(bool pause) { - if (_progressAnimationController != null) { - if (pause) { - _progressAnimationController!.stop(); - } else { - _progressAnimationController!.forward(); - } - } - if (_zoomAnimationController != null) { - if (pause) { - _zoomAnimationController!.stop(); - } else { - _zoomAnimationController!.forward(); - } + if (pause) { + _progressAnimationController?.stop(); + _zoomAnimationController?.stop(); + } else { + _progressAnimationController?.forward(); + _zoomAnimationController?.forward(); } } @@ -188,7 +175,7 @@ class _FullScreenMemoryState extends State { } void onFinalFileLoad(int duration) { - if (_progressAnimationController!.isAnimating == true) { + if (_progressAnimationController?.isAnimating == true) { _progressAnimationController!.stop(); } durationNotifier.value = Duration(seconds: duration); @@ -203,6 +190,22 @@ class _FullScreenMemoryState extends State { ..forward(); } + void _goToNext(FullScreenMemoryData inheritedData) { + final currentIndex = inheritedData.indexNotifier.value; + if (currentIndex < inheritedData.memories.length - 1) { + inheritedData.indexNotifier.value += 1; + _resetAnimation(); + } + } + + void _goToPrevious(FullScreenMemoryData inheritedData) { + final currentIndex = inheritedData.indexNotifier.value; + if (currentIndex > 0) { + inheritedData.indexNotifier.value -= 1; + _resetAnimation(); + } + } + @override Widget build(BuildContext context) { final inheritedData = FullScreenMemoryData.of(context)!; @@ -217,15 +220,10 @@ class _FullScreenMemoryState extends State { title: ValueListenableBuilder( valueListenable: inheritedData.indexNotifier, child: InkWell( - onTap: () { - Navigator.pop(context); - }, + onTap: () => Navigator.pop(context), child: const Padding( padding: EdgeInsets.fromLTRB(4, 8, 8, 8), - child: Icon( - Icons.close, - color: Colors.white, //same for both themes - ), + child: Icon(Icons.close, color: Colors.white), ), ), builder: (context, value, child) { @@ -246,15 +244,7 @@ class _FullScreenMemoryState extends State { _progressAnimationController = controller; }, onComplete: () { - final currentIndex = - inheritedData.indexNotifier.value; - if (currentIndex < - inheritedData.memories.length - 1) { - _pageController!.nextPage( - duration: const Duration(milliseconds: 250), - curve: Curves.ease, - ); - } + _goToNext(inheritedData); }, ); }, @@ -273,7 +263,7 @@ class _FullScreenMemoryState extends State { style: Theme.of(context).textTheme.titleMedium!.copyWith( fontSize: 14, color: Colors.white, - ), //same for both themes + ), ), ], ), @@ -282,66 +272,51 @@ class _FullScreenMemoryState extends State { }, ), flexibleSpace: Container( - decoration: BoxDecoration( + decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ - Colors.black.withOpacity(0.6), - Colors.black.withOpacity(0.5), + Colors.black54, + Colors.black45, Colors.transparent, ], - stops: const [0, 0.6, 1], + stops: [0, 0.6, 1], ), ), ), - backgroundColor: const Color(0x00000000), + backgroundColor: Colors.transparent, elevation: 0, ), body: Stack( alignment: Alignment.bottomCenter, children: [ const MemoryBackDrop(), - PageView.builder( - controller: _pageController ??= PageController( - initialPage: widget.initialIndex, - ), - physics: const BouncingScrollPhysics(), - itemBuilder: (context, index) { + ValueListenableBuilder( + valueListenable: inheritedData.indexNotifier, + builder: (context, index, _) { if (index < inheritedData.memories.length - 1) { final nextFile = inheritedData.memories[index + 1].file; preloadThumbnail(nextFile); preloadFile(nextFile); } - final currentFile = inheritedData.memories[index].file; - final isVideo = currentFile.fileType == FileType.video; + final currentMemory = inheritedData.memories[index]; + final isVideo = currentMemory.file.fileType == FileType.video; + final currentFile = currentMemory.file; + return GestureDetector( onTapDown: (TapDownDetails details) { final screenWidth = MediaQuery.of(context).size.width; final edgeWidth = screenWidth * 0.20; if (details.localPosition.dx < edgeWidth) { - if (index > 0) { - _pageController!.previousPage( - duration: const Duration(milliseconds: 250), - curve: Curves.ease, - ); - } + _goToPrevious(inheritedData); } else if (details.localPosition.dx > screenWidth - edgeWidth) { - if (index < (inheritedData.memories.length - 1)) { - _pageController!.nextPage( - duration: const Duration(milliseconds: 250), - curve: Curves.ease, - ); - } + _goToNext(inheritedData); } }, - onLongPress: () { - isVideo ? null: _toggleAnimation(true); - }, - onLongPressUp: () { - isVideo ? null : _toggleAnimation(false); - }, + onLongPress: () => isVideo ? null : _toggleAnimation(true), + onLongPressUp: () => isVideo ? null : _toggleAnimation(false), child: MemoriesZoomWidget( scaleController: (controller) { _zoomAnimationController = controller; @@ -349,12 +324,11 @@ class _FullScreenMemoryState extends State { zoomIn: index % 2 == 0, isVideo: isVideo, child: FileWidget( - inheritedData.memories[index].file, + currentFile, autoPlay: false, tagPrefix: "memories", - backgroundDecoration: const BoxDecoration( - color: Colors.transparent, - ), + backgroundDecoration: + const BoxDecoration(color: Colors.transparent), isFromMemories: true, playbackCallback: (isPlaying) { _toggleAnimation(!isPlaying); @@ -366,23 +340,13 @@ class _FullScreenMemoryState extends State { ), ); }, - onPageChanged: (index) async { - unawaited( - memoriesCacheService.markMemoryAsSeen( - inheritedData.memories[index], - inheritedData.memories.length == index + 1, - ), - ); - inheritedData.indexNotifier.value = index; - _resetAnimation(); - }, - itemCount: inheritedData.memories.length, ), SafeArea( top: false, child: Padding( padding: const EdgeInsets.only(bottom: 72), child: ValueListenableBuilder( + valueListenable: _showTitle, builder: (context, value, _) { return AnimatedSwitcher( duration: const Duration(milliseconds: 250), @@ -398,8 +362,7 @@ class _FullScreenMemoryState extends State { style: getEnteTextTheme(context) .largeBold .copyWith( - color: - Colors.white, //same for both themes + color: Colors.white, ), ), ), @@ -409,7 +372,6 @@ class _FullScreenMemoryState extends State { : const MemoryCounter(), ); }, - valueListenable: _showTitle, ), ), ), diff --git a/mobile/lib/ui/home/memories/memories_widget.dart b/mobile/lib/ui/home/memories/memories_widget.dart index e3c9f69204..1fef9d45a2 100644 --- a/mobile/lib/ui/home/memories/memories_widget.dart +++ b/mobile/lib/ui/home/memories/memories_widget.dart @@ -132,6 +132,7 @@ class _MemoriesWidgetState extends State { itemBuilder: (context, itemIndex) { return MemoryCoverWidget( memories: collatedMemories[itemIndex].$1, + allMemories: collatedMemories.map((e) => e.$1).toList(), controller: _controller, maxHeight: _maxHeight, maxWidth: _maxWidth, diff --git a/mobile/lib/ui/home/memories/memory_cover_widget.dart b/mobile/lib/ui/home/memories/memory_cover_widget.dart index f2754806df..16449a4191 100644 --- a/mobile/lib/ui/home/memories/memory_cover_widget.dart +++ b/mobile/lib/ui/home/memories/memory_cover_widget.dart @@ -4,12 +4,14 @@ import "package:photos/models/memories/memory.dart"; import "package:photos/theme/colors.dart"; import "package:photos/theme/effects.dart"; import "package:photos/theme/ente_theme.dart"; -import "package:photos/ui/home/memories/full_screen_memory.dart"; +// import "package:photos/ui/home/memories/full_screen_memory.dart"; +import "package:photos/ui/home/memories/temp.dart"; import "package:photos/ui/viewer/file/thumbnail_widget.dart"; import "package:photos/utils/navigation_util.dart"; class MemoryCoverWidget extends StatefulWidget { final List memories; + final List> allMemories; final ScrollController controller; final double maxHeight; final double maxWidth; @@ -20,6 +22,7 @@ class MemoryCoverWidget extends StatefulWidget { const MemoryCoverWidget({ required this.memories, + required this.allMemories, required this.controller, required this.maxHeight, required this.maxWidth, @@ -59,12 +62,17 @@ class _MemoryCoverWidgetState extends State { onTap: () async { await routeToPage( context, - FullScreenMemoryDataUpdater( + // FullScreenMemoryDataUpdater( + // initialIndex: index, + // memories: widget.memories, + // child: FullScreenMemory(title, index), + // ), + // forceCustomPageRoute: true, + TempPage( + allMemories: widget.allMemories, + page: widget.allMemories.length, initialIndex: index, - memories: widget.memories, - child: FullScreenMemory(title, index), ), - forceCustomPageRoute: true, ); setState(() {}); }, //Adding this row is a workaround for making height of memory cover @@ -73,8 +81,8 @@ class _MemoryCoverWidgetState extends State { child: Row( children: [ Container( - height: widget.maxHeight , - width: widget.maxWidth , + height: widget.maxHeight, + width: widget.maxWidth, decoration: BoxDecoration( boxShadow: brightness == Brightness.dark ? [ @@ -114,7 +122,7 @@ class _MemoryCoverWidgetState extends State { ), ), Positioned( - bottom: 8 , + bottom: 8, child: SizedBox( width: widget.maxWidth, child: Padding( @@ -162,7 +170,7 @@ class _MemoryCoverWidgetState extends State { ), ), Positioned( - bottom: 8 , + bottom: 8, child: SizedBox( width: widget.maxWidth, child: Padding( diff --git a/mobile/lib/ui/home/memories/temp.dart b/mobile/lib/ui/home/memories/temp.dart new file mode 100644 index 0000000000..48a5592019 --- /dev/null +++ b/mobile/lib/ui/home/memories/temp.dart @@ -0,0 +1,54 @@ +import 'package:flutter/material.dart'; +import "package:photos/models/memories/memory.dart"; +import "package:photos/ui/home/memories/full_screen_memory.dart"; + +class TempPage extends StatelessWidget { + final int page; + final int initialIndex; + final List> allMemories; + + const TempPage({ + super.key, + required this.page, + required this.allMemories, + this.initialIndex = 0, + }); + + static Route route({ + required List> allMemories, + required List titles, + int initialIndex = 0, + }) { + return MaterialPageRoute( + builder: (_) => TempPage( + page: allMemories.length, + initialIndex: initialIndex, + allMemories: allMemories, + ), + ); + } + + @override + Widget build(BuildContext context) { + final pageController = PageController(initialPage: initialIndex); + + return Scaffold( + body: PageView.builder( + controller: pageController, + physics: const BouncingScrollPhysics(), + itemCount: allMemories.length, + itemBuilder: (context, index) { + return FullScreenMemoryDataUpdater( + initialIndex: 0, + memories: allMemories[index], + child:const FullScreenMemory( + + "asdasdasd", + 0, + ), + ); + }, + ), + ); + } +} \ No newline at end of file diff --git a/mobile/lib/ui/notification/update/change_log_page.dart b/mobile/lib/ui/notification/update/change_log_page.dart index 99e535721c..9907cba6ea 100644 --- a/mobile/lib/ui/notification/update/change_log_page.dart +++ b/mobile/lib/ui/notification/update/change_log_page.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; -import "package:photos/generated/l10n.dart"; -import "package:photos/l10n/l10n.dart"; +import "package:photos/generated/l10n.dart"; import "package:photos/service_locator.dart"; import 'package:photos/theme/ente_theme.dart'; import 'package:photos/ui/components/buttons/button_widget.dart'; From 3d58698bfccf6531447dd020142ffb621b75f909 Mon Sep 17 00:00:00 2001 From: AmanRajSinghMourya Date: Tue, 10 Jun 2025 17:05:25 +0530 Subject: [PATCH 2/8] Use better name + code refractoring --- .../ui/home/memories/all_memories_page.dart | 107 ++++++++++++++++++ mobile/lib/ui/home/memories/temp.dart | 54 --------- 2 files changed, 107 insertions(+), 54 deletions(-) create mode 100644 mobile/lib/ui/home/memories/all_memories_page.dart delete mode 100644 mobile/lib/ui/home/memories/temp.dart diff --git a/mobile/lib/ui/home/memories/all_memories_page.dart b/mobile/lib/ui/home/memories/all_memories_page.dart new file mode 100644 index 0000000000..159559062d --- /dev/null +++ b/mobile/lib/ui/home/memories/all_memories_page.dart @@ -0,0 +1,107 @@ +import 'package:flutter/material.dart'; +import "package:photos/models/memories/memory.dart"; +import "package:photos/ui/home/memories/full_screen_memory.dart"; + +class AllMemoriesPage extends StatefulWidget { + final int initialPageIndex; + final List> allMemories; + final List allTitles; + + const AllMemoriesPage({ + super.key, + required this.allMemories, + required this.allTitles, + required this.initialPageIndex, + }); + + @override + State createState() => _AllMemoriesPageState(); +} + +class _AllMemoriesPageState extends State + with SingleTickerProviderStateMixin { + late PageController pageController; + + @override + void initState() { + super.initState(); + pageController = PageController(initialPage: widget.initialPageIndex); + } + + @override + void dispose() { + pageController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: PageView.builder( + controller: pageController, + physics: const BouncingScrollPhysics(), + itemCount: widget.allMemories.length, + itemBuilder: (context, index) { + return AnimatedBuilder( + animation: pageController, + builder: (context, child) { + double value = 1.0; + if (pageController.position.haveDimensions) { + value = pageController.page! - index; + value = (1 - (value.abs() * 0.5)).clamp(0.0, 1.0); + } + return Transform.scale( + scale: value, + child: Opacity( + opacity: value, + child: FullScreenMemoryDataUpdater( + initialIndex: _getNextMemoryIndex(index), + memories: widget.allMemories[index], + child: FullScreenMemory( + widget.allTitles[index], + _getNextMemoryIndex(index), + onNextMemory: index < widget.allMemories.length - 1 + ? () => pageController.nextPage( + duration: const Duration(milliseconds: 250), + curve: Curves.ease, + ) + : null, + onPreviousMemory: index > 0 + ? () => pageController.previousPage( + duration: const Duration(milliseconds: 250), + curve: Curves.ease, + ) + : null, + ), + ), + ), + ); + }, + ); + }, + ), + ); + } + + int _getNextMemoryIndex(int currentIndex) { + int lastSeenIndex = 0; + int lastSeenTimestamp = 0; + for (var index = 0; + index < widget.allMemories[currentIndex].length; + index++) { + final memory = widget.allMemories[currentIndex][index]; + if (!memory.isSeen()) { + return index; + } else { + if (memory.seenTime() > lastSeenTimestamp) { + lastSeenIndex = index; + lastSeenTimestamp = memory.seenTime(); + } + } + } + if (lastSeenIndex == widget.allMemories[currentIndex].length - 1) { + return 0; + } + return lastSeenIndex + 1; + } +} diff --git a/mobile/lib/ui/home/memories/temp.dart b/mobile/lib/ui/home/memories/temp.dart deleted file mode 100644 index 48a5592019..0000000000 --- a/mobile/lib/ui/home/memories/temp.dart +++ /dev/null @@ -1,54 +0,0 @@ -import 'package:flutter/material.dart'; -import "package:photos/models/memories/memory.dart"; -import "package:photos/ui/home/memories/full_screen_memory.dart"; - -class TempPage extends StatelessWidget { - final int page; - final int initialIndex; - final List> allMemories; - - const TempPage({ - super.key, - required this.page, - required this.allMemories, - this.initialIndex = 0, - }); - - static Route route({ - required List> allMemories, - required List titles, - int initialIndex = 0, - }) { - return MaterialPageRoute( - builder: (_) => TempPage( - page: allMemories.length, - initialIndex: initialIndex, - allMemories: allMemories, - ), - ); - } - - @override - Widget build(BuildContext context) { - final pageController = PageController(initialPage: initialIndex); - - return Scaffold( - body: PageView.builder( - controller: pageController, - physics: const BouncingScrollPhysics(), - itemCount: allMemories.length, - itemBuilder: (context, index) { - return FullScreenMemoryDataUpdater( - initialIndex: 0, - memories: allMemories[index], - child:const FullScreenMemory( - - "asdasdasd", - 0, - ), - ); - }, - ), - ); - } -} \ No newline at end of file From 6a796debb848c8a91990bbd81008a45f5fd25093 Mon Sep 17 00:00:00 2001 From: AmanRajSinghMourya Date: Tue, 10 Jun 2025 18:56:49 +0530 Subject: [PATCH 3/8] Callback to go to next/previous memories --- .../ui/home/memories/full_screen_memory.dart | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/mobile/lib/ui/home/memories/full_screen_memory.dart b/mobile/lib/ui/home/memories/full_screen_memory.dart index 20c7bc8293..57ab2a8cd1 100644 --- a/mobile/lib/ui/home/memories/full_screen_memory.dart +++ b/mobile/lib/ui/home/memories/full_screen_memory.dart @@ -123,9 +123,14 @@ class FullScreenMemoryData extends InheritedWidget { class FullScreenMemory extends StatefulWidget { final String title; final int initialIndex; + final VoidCallback? onNextMemory; + final VoidCallback? onPreviousMemory; + const FullScreenMemory( this.title, this.initialIndex, { + this.onNextMemory, + this.onPreviousMemory, super.key, }); @@ -194,7 +199,9 @@ class _FullScreenMemoryState extends State { final currentIndex = inheritedData.indexNotifier.value; if (currentIndex < inheritedData.memories.length - 1) { inheritedData.indexNotifier.value += 1; - _resetAnimation(); + _onPageChange(inheritedData, currentIndex + 1); + } else if (widget.onNextMemory != null) { + widget.onNextMemory!(); } } @@ -202,10 +209,23 @@ class _FullScreenMemoryState extends State { final currentIndex = inheritedData.indexNotifier.value; if (currentIndex > 0) { inheritedData.indexNotifier.value -= 1; - _resetAnimation(); + _onPageChange(inheritedData, currentIndex - 1); + } else if (widget.onPreviousMemory != null) { + widget.onPreviousMemory!(); } } + void _onPageChange(FullScreenMemoryData inheritedData, int index) { + unawaited( + memoriesCacheService.markMemoryAsSeen( + inheritedData.memories[index], + inheritedData.memories.length == index + 1, + ), + ); + inheritedData.indexNotifier.value = index; + _resetAnimation(); + } + @override Widget build(BuildContext context) { final inheritedData = FullScreenMemoryData.of(context)!; From 1e5abf20cd32b1ff6ef8fd1cc7d8e3422dbf5724 Mon Sep 17 00:00:00 2001 From: AmanRajSinghMourya Date: Tue, 10 Jun 2025 18:58:19 +0530 Subject: [PATCH 4/8] Improve memory navigation and data handling in memory widgets --- .../ui/home/memories/all_memories_page.dart | 59 ++++++++----------- .../lib/ui/home/memories/memories_widget.dart | 2 + .../ui/home/memories/memory_cover_widget.dart | 21 +++---- 3 files changed, 35 insertions(+), 47 deletions(-) diff --git a/mobile/lib/ui/home/memories/all_memories_page.dart b/mobile/lib/ui/home/memories/all_memories_page.dart index 159559062d..e3158d2d38 100644 --- a/mobile/lib/ui/home/memories/all_memories_page.dart +++ b/mobile/lib/ui/home/memories/all_memories_page.dart @@ -40,43 +40,32 @@ class _AllMemoriesPageState extends State body: PageView.builder( controller: pageController, physics: const BouncingScrollPhysics(), + hitTestBehavior: HitTestBehavior.translucent, itemCount: widget.allMemories.length, itemBuilder: (context, index) { - return AnimatedBuilder( - animation: pageController, - builder: (context, child) { - double value = 1.0; - if (pageController.position.haveDimensions) { - value = pageController.page! - index; - value = (1 - (value.abs() * 0.5)).clamp(0.0, 1.0); - } - return Transform.scale( - scale: value, - child: Opacity( - opacity: value, - child: FullScreenMemoryDataUpdater( - initialIndex: _getNextMemoryIndex(index), - memories: widget.allMemories[index], - child: FullScreenMemory( - widget.allTitles[index], - _getNextMemoryIndex(index), - onNextMemory: index < widget.allMemories.length - 1 - ? () => pageController.nextPage( - duration: const Duration(milliseconds: 250), - curve: Curves.ease, - ) - : null, - onPreviousMemory: index > 0 - ? () => pageController.previousPage( - duration: const Duration(milliseconds: 250), - curve: Curves.ease, - ) - : null, - ), - ), - ), - ); - }, + final initialMemoryIndex = _getNextMemoryIndex(index); + if (widget.allMemories[index].isEmpty) { + return const SizedBox.shrink(); + } + return FullScreenMemoryDataUpdater( + initialIndex: initialMemoryIndex, + memories: widget.allMemories[index], + child: FullScreenMemory( + widget.allTitles[index], + initialMemoryIndex, + onNextMemory: index < widget.allMemories.length - 1 + ? () => pageController.nextPage( + duration: const Duration(milliseconds: 250), + curve: Curves.ease, + ) + : null, + onPreviousMemory: index > 0 + ? () => pageController.previousPage( + duration: const Duration(milliseconds: 250), + curve: Curves.ease, + ) + : null, + ), ); }, ), diff --git a/mobile/lib/ui/home/memories/memories_widget.dart b/mobile/lib/ui/home/memories/memories_widget.dart index 1fef9d45a2..5a47a7c46f 100644 --- a/mobile/lib/ui/home/memories/memories_widget.dart +++ b/mobile/lib/ui/home/memories/memories_widget.dart @@ -137,6 +137,8 @@ class _MemoriesWidgetState extends State { maxHeight: _maxHeight, maxWidth: _maxWidth, title: collatedMemories[itemIndex].$2, + allTitle: collatedMemories.map((e) => e.$2).toList(), + currentMemoryIndex: itemIndex, ); }, ), diff --git a/mobile/lib/ui/home/memories/memory_cover_widget.dart b/mobile/lib/ui/home/memories/memory_cover_widget.dart index 16449a4191..57b47a1b3b 100644 --- a/mobile/lib/ui/home/memories/memory_cover_widget.dart +++ b/mobile/lib/ui/home/memories/memory_cover_widget.dart @@ -4,8 +4,7 @@ import "package:photos/models/memories/memory.dart"; import "package:photos/theme/colors.dart"; import "package:photos/theme/effects.dart"; import "package:photos/theme/ente_theme.dart"; -// import "package:photos/ui/home/memories/full_screen_memory.dart"; -import "package:photos/ui/home/memories/temp.dart"; +import "package:photos/ui/home/memories/all_memories_page.dart"; import "package:photos/ui/viewer/file/thumbnail_widget.dart"; import "package:photos/utils/navigation_util.dart"; @@ -19,6 +18,8 @@ class MemoryCoverWidget extends StatefulWidget { static const aspectRatio = 0.68; static const horizontalPadding = 2.5; final String title; + final List allTitle; + final int currentMemoryIndex; const MemoryCoverWidget({ required this.memories, @@ -27,6 +28,8 @@ class MemoryCoverWidget extends StatefulWidget { required this.maxHeight, required this.maxWidth, required this.title, + required this.allTitle, + required this.currentMemoryIndex, super.key, }); @@ -59,19 +62,13 @@ class _MemoryCoverWidgetState extends State { horizontal: MemoryCoverWidget.horizontalPadding, ), child: GestureDetector( - onTap: () async { + onTap: () async { await routeToPage( context, - // FullScreenMemoryDataUpdater( - // initialIndex: index, - // memories: widget.memories, - // child: FullScreenMemory(title, index), - // ), - // forceCustomPageRoute: true, - TempPage( + AllMemoriesPage( + initialPageIndex: widget.currentMemoryIndex, allMemories: widget.allMemories, - page: widget.allMemories.length, - initialIndex: index, + allTitles: widget.allTitle, ), ); setState(() {}); From 287e6da537c6478ac0bceaa08afeee5f5aeb9e5b Mon Sep 17 00:00:00 2001 From: AmanRajSinghMourya Date: Wed, 11 Jun 2025 14:13:06 +0530 Subject: [PATCH 5/8] To avoid shuffling of memories when user see all the files in one memory --- mobile/lib/ui/home/memories/full_screen_memory.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/lib/ui/home/memories/full_screen_memory.dart b/mobile/lib/ui/home/memories/full_screen_memory.dart index 57ab2a8cd1..d9dc7879ce 100644 --- a/mobile/lib/ui/home/memories/full_screen_memory.dart +++ b/mobile/lib/ui/home/memories/full_screen_memory.dart @@ -219,7 +219,7 @@ class _FullScreenMemoryState extends State { unawaited( memoriesCacheService.markMemoryAsSeen( inheritedData.memories[index], - inheritedData.memories.length == index + 1, + false, ), ); inheritedData.indexNotifier.value = index; From 29962197d73068d30a47584f4d96ed240807bf26 Mon Sep 17 00:00:00 2001 From: AmanRajSinghMourya Date: Wed, 11 Jun 2025 14:13:22 +0530 Subject: [PATCH 6/8] Refractor --- mobile/lib/ui/home/memories/all_memories_page.dart | 3 --- 1 file changed, 3 deletions(-) diff --git a/mobile/lib/ui/home/memories/all_memories_page.dart b/mobile/lib/ui/home/memories/all_memories_page.dart index e3158d2d38..9bede1ea73 100644 --- a/mobile/lib/ui/home/memories/all_memories_page.dart +++ b/mobile/lib/ui/home/memories/all_memories_page.dart @@ -44,9 +44,6 @@ class _AllMemoriesPageState extends State itemCount: widget.allMemories.length, itemBuilder: (context, index) { final initialMemoryIndex = _getNextMemoryIndex(index); - if (widget.allMemories[index].isEmpty) { - return const SizedBox.shrink(); - } return FullScreenMemoryDataUpdater( initialIndex: initialMemoryIndex, memories: widget.allMemories[index], From 55dd0ea830a7612c261216f2f34742cac36adf73 Mon Sep 17 00:00:00 2001 From: AmanRajSinghMourya Date: Wed, 11 Jun 2025 16:27:23 +0530 Subject: [PATCH 7/8] Refactor tap handling in video widgets to prevent interaction when viewing memories --- .../file/video_widget_media_kit_common.dart | 20 ++++++++++--------- .../ui/viewer/file/video_widget_native.dart | 18 +++++++++-------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/mobile/lib/ui/viewer/file/video_widget_media_kit_common.dart b/mobile/lib/ui/viewer/file/video_widget_media_kit_common.dart index 2e50e0adc0..fedf3d35c7 100644 --- a/mobile/lib/ui/viewer/file/video_widget_media_kit_common.dart +++ b/mobile/lib/ui/viewer/file/video_widget_media_kit_common.dart @@ -99,15 +99,17 @@ class _VideoWidgetState extends State { children: [ GestureDetector( behavior: HitTestBehavior.opaque, - onTap: () { - if (widget.isFromMemories) return; - showControlsNotifier.value = !showControlsNotifier.value; - if (widget.playbackCallback != null) { - widget.playbackCallback!( - !showControlsNotifier.value, - ); - } - }, + onTap: widget.isFromMemories + ? null + : () { + showControlsNotifier.value = + !showControlsNotifier.value; + if (widget.playbackCallback != null) { + widget.playbackCallback!( + !showControlsNotifier.value, + ); + } + }, onLongPress: () { if (widget.isFromMemories) { widget.playbackCallback?.call(false); diff --git a/mobile/lib/ui/viewer/file/video_widget_native.dart b/mobile/lib/ui/viewer/file/video_widget_native.dart index acf428482f..5afe6e4351 100644 --- a/mobile/lib/ui/viewer/file/video_widget_native.dart +++ b/mobile/lib/ui/viewer/file/video_widget_native.dart @@ -284,14 +284,16 @@ class _VideoWidgetNativeState extends State ), GestureDetector( behavior: HitTestBehavior.opaque, - onTap: () { - if (widget.isFromMemories) return; - _showControls.value = !_showControls.value; - if (widget.playbackCallback != null) { - widget.playbackCallback!(!_showControls.value); - } - _elTooltipController.hide(); - }, + onTap: widget.isFromMemories + ? null + : () { + _showControls.value = !_showControls.value; + if (widget.playbackCallback != null) { + widget + .playbackCallback!(!_showControls.value); + } + _elTooltipController.hide(); + }, onLongPress: () { if (widget.isFromMemories) { widget.playbackCallback?.call(false); From e51506b9f80b2180cc1fea35245aee4a3d85aeb5 Mon Sep 17 00:00:00 2001 From: AmanRajSinghMourya Date: Wed, 11 Jun 2025 16:28:34 +0530 Subject: [PATCH 8/8] Pause animtaion when delete/share action is performed --- .../ui/home/memories/full_screen_memory.dart | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/mobile/lib/ui/home/memories/full_screen_memory.dart b/mobile/lib/ui/home/memories/full_screen_memory.dart index d9dc7879ce..eb51a66f9f 100644 --- a/mobile/lib/ui/home/memories/full_screen_memory.dart +++ b/mobile/lib/ui/home/memories/full_screen_memory.dart @@ -325,7 +325,7 @@ class _FullScreenMemoryState extends State { final currentFile = currentMemory.file; return GestureDetector( - onTapDown: (TapDownDetails details) { + onTapUp: (TapUpDetails details) { final screenWidth = MediaQuery.of(context).size.width; final edgeWidth = screenWidth * 0.20; if (details.localPosition.dx < edgeWidth) { @@ -409,6 +409,8 @@ class BottomIcons extends StatelessWidget { @override Widget build(BuildContext context) { final inheritedData = FullScreenMemoryData.of(context)!; + final fullScreenState = + context.findAncestorStateOfType<_FullScreenMemoryState>(); return ValueListenableBuilder( valueListenable: inheritedData.indexNotifier, @@ -420,8 +422,10 @@ class BottomIcons extends StatelessWidget { Platform.isAndroid ? Icons.info_outline : CupertinoIcons.info, color: Colors.white, //same for both themes ), - onPressed: () { - showDetailsSheet(context, currentFile); + onPressed: () async { + fullScreenState?._toggleAnimation(true); + await showDetailsSheet(context, currentFile); + fullScreenState?._toggleAnimation(false); }, ), ]; @@ -437,6 +441,7 @@ class BottomIcons extends StatelessWidget { color: Colors.white, //same for both themes ), onPressed: () async { + fullScreenState?._toggleAnimation(true); await showSingleFileDeleteSheet( context, inheritedData @@ -449,6 +454,7 @@ class BottomIcons extends StatelessWidget { }, }, ); + fullScreenState?._toggleAnimation(false); }, ), SizedBox( @@ -463,8 +469,10 @@ class BottomIcons extends StatelessWidget { Icons.adaptive.share, color: Colors.white, //same for both themes ), - onPressed: () { - share(context, [currentFile]); + onPressed: () async { + fullScreenState?._toggleAnimation(true); + await share(context, [currentFile]); + fullScreenState?._toggleAnimation(false); }, ), );