From 6e4db6c0dfb14ec282e78189a3ee7a1bf8859663 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Thu, 28 Mar 2024 14:57:19 +0530 Subject: [PATCH 01/84] add cast to dependencies and update flutter --- mobile/README.md | 2 +- mobile/pubspec.lock | 59 ++++++++++++++++++++++++++++++++++++++++----- mobile/pubspec.yaml | 2 ++ 3 files changed, 56 insertions(+), 7 deletions(-) diff --git a/mobile/README.md b/mobile/README.md index 005d303b6b..f9b6c56874 100644 --- a/mobile/README.md +++ b/mobile/README.md @@ -46,7 +46,7 @@ You can alternatively install the build from PlayStore or F-Droid. ## 🧑‍💻 Building from source -1. [Install Flutter v3.13.4](https://flutter.dev/docs/get-started/install). +1. [Install Flutter v3.13.6](https://flutter.dev/docs/get-started/install). 2. Pull in all submodules with `git submodule update --init --recursive` diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index 35a9494fb0..270b493daa 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -113,6 +113,38 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.6" + bonsoir: + dependency: transitive + description: + name: bonsoir + sha256: "800d77c0581fff06cc43ef2b7723dfe5ee9b899ab0fdf80fb1c7b8829a5deb5c" + url: "https://pub.dev" + source: hosted + version: "3.0.0+1" + bonsoir_android: + dependency: transitive + description: + name: bonsoir_android + sha256: "7207c36fd7e0f3c7c2d8cf353f02bd640d96e2387d575837f8ac051c9cbf4aa7" + url: "https://pub.dev" + source: hosted + version: "3.0.0+1" + bonsoir_darwin: + dependency: transitive + description: + name: bonsoir_darwin + sha256: "7211042c85da2d6efa80c0976bbd9568f2b63624097779847548ed4530675ade" + url: "https://pub.dev" + source: hosted + version: "3.0.0" + bonsoir_platform_interface: + dependency: transitive + description: + name: bonsoir_platform_interface + sha256: "64d57cd52bd477b4891e9b9d419e6408da171ed9e0efc8aa716e7e343d5d93ad" + url: "https://pub.dev" + source: hosted + version: "3.0.0" boolean_selector: dependency: transitive description: @@ -209,6 +241,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" + cast: + dependency: "direct main" + description: + name: cast + sha256: b70f6be547a53481dffec93ad3cc4974fae5ed707f0b677d4a50c329d7299b98 + url: "https://pub.dev" + source: hosted + version: "2.0.0" characters: dependency: transitive description: @@ -285,11 +325,10 @@ packages: connectivity_plus: dependency: "direct main" description: - path: "packages/connectivity_plus/connectivity_plus" - ref: check_mobile_first - resolved-ref: "452aa4b6448adbd3a9e592b82da3e9d355af2125" - url: "https://github.com/ente-io/plus_plugins.git" - source: git + name: connectivity_plus + sha256: "77a180d6938f78ca7d2382d2240eb626c0f6a735d0bfdce227d8ffb80f95c48b" + url: "https://pub.dev" + source: hosted version: "4.0.2" connectivity_plus_platform_interface: dependency: transitive @@ -1627,6 +1666,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.0" + protobuf: + dependency: transitive + description: + name: protobuf + sha256: "68645b24e0716782e58948f8467fd42a880f255096a821f9e7d0ec625b00c84d" + url: "https://pub.dev" + source: hosted + version: "3.1.0" provider: dependency: "direct main" description: @@ -2490,5 +2537,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.1.0 <4.0.0" + dart: ">=3.1.3 <4.0.0" flutter: ">=3.13.0" diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index b4e2e450e6..8d65409dcb 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -27,6 +27,7 @@ dependencies: battery_info: ^1.1.1 bip39: ^1.0.6 cached_network_image: ^3.0.0 + cast: ^2.0.0 chewie: git: url: https://github.com/ente-io/chewie.git @@ -175,6 +176,7 @@ dependencies: widgets_to_image: ^0.0.2 dependency_overrides: + connectivity_plus: ^4.0.0 # current fork of tfite_flutter_helper depends on ffi: ^1.x.x # but we need ffi: ^2.0.1 for newer packages. The original tfite_flutter_helper # From dabda8e744192a24a69d6f00a30943150d416d61 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Thu, 28 Mar 2024 16:32:59 +0530 Subject: [PATCH 02/84] upgrade photo_manager and flutter --- mobile/README.md | 2 +- mobile/lib/db/device_files_db.dart | 7 +- mobile/pubspec.lock | 246 ++++++++++++++++------------- mobile/pubspec.yaml | 2 +- 4 files changed, 141 insertions(+), 116 deletions(-) diff --git a/mobile/README.md b/mobile/README.md index f9b6c56874..f2889a9ce1 100644 --- a/mobile/README.md +++ b/mobile/README.md @@ -46,7 +46,7 @@ You can alternatively install the build from PlayStore or F-Droid. ## 🧑‍💻 Building from source -1. [Install Flutter v3.13.6](https://flutter.dev/docs/get-started/install). +1. [Install Flutter v3.16.0](https://flutter.dev/docs/get-started/install). 2. Pull in all submodules with `git submodule update --init --recursive` diff --git a/mobile/lib/db/device_files_db.dart b/mobile/lib/db/device_files_db.dart index ec1074eae8..5009dc0e0d 100644 --- a/mobile/lib/db/device_files_db.dart +++ b/mobile/lib/db/device_files_db.dart @@ -181,6 +181,7 @@ extension DeviceFiles on FilesDB { final Set existingPathIds = await getDevicePathIDs(); for (Tuple2 tup in devicePathInfo) { final AssetPathEntity pathEntity = tup.item1; + final assetCount = await pathEntity.assetCountAsync; final String localID = tup.item2; final bool shouldUpdate = existingPathIds.contains(pathEntity.id); if (shouldUpdate) { @@ -190,11 +191,11 @@ extension DeviceFiles on FilesDB { [ pathEntity.name, localID, - pathEntity.assetCount, + assetCount, pathEntity.id, pathEntity.name, localID, - pathEntity.assetCount, + assetCount, ], ); if (rowUpdated > 0) { @@ -208,7 +209,7 @@ extension DeviceFiles on FilesDB { { "id": pathEntity.id, "name": pathEntity.name, - "count": pathEntity.assetCount, + "count": assetCount, "cover_id": localID, "should_backup": shouldBackup ? _sqlBoolTrue : _sqlBoolFalse, }, diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index 270b493daa..41c30e2ce8 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -13,18 +13,18 @@ packages: dependency: transitive description: name: _flutterfire_internals - sha256: f5628cd9c92ed11083f425fd1f8f1bc60ecdda458c81d73b143aeda036c35fe7 + sha256: "4eec93681221723a686ad580c2e7d960e1017cf1a4e0a263c2573c2c6b0bf5cd" url: "https://pub.dev" source: hosted - version: "1.3.16" + version: "1.3.25" adaptive_theme: dependency: "direct main" description: name: adaptive_theme - sha256: b0c4c35b22ef8226757881fe4dce38c40a06c551bca83236022ec7613e157c83 + sha256: f4ee609b464e5efc68131d9d15ba9aa1de4e3b5ede64be17781c6e19a52d637d url: "https://pub.dev" source: hosted - version: "3.5.0" + version: "3.6.0" analyzer: dependency: transitive description: @@ -93,10 +93,10 @@ packages: dependency: "direct main" description: name: background_fetch - sha256: f70b28a0f7a3156195e9742229696f004ea3bf10f74039b7bf4c78a74fbda8a4 + sha256: dbffec0317ccdef6e2014cb543e147f52441e29c4fcb53dfd23558c4d92ddece url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.3.2" battery_info: dependency: "direct main" description: @@ -197,10 +197,10 @@ packages: dependency: transitive description: name: build_runner_core - sha256: c9e32d21dd6626b5c163d48b037ce906bbe428bc23ab77bcd77bb21e593b6185 + sha256: "4ae8ffe5ac758da294ecf1802f2aff01558d8b1b00616aa7538ea9a8a5d50799" url: "https://pub.dev" source: hosted - version: "7.2.11" + version: "7.3.0" built_collection: dependency: transitive description: @@ -213,10 +213,10 @@ packages: dependency: transitive description: name: built_value - sha256: a3ec2e0f967bc47f69f95009bb93db936288d61d5343b9436e378b28a2f830c6 + sha256: fedde275e0a6b798c3296963c5cd224e3e1b55d0e478d5b7e65e6b540f363a0e url: "https://pub.dev" source: hosted - version: "8.9.0" + version: "8.9.1" cached_network_image: dependency: "direct main" description: @@ -309,10 +309,10 @@ packages: dependency: "direct main" description: name: collection - sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.2" + version: "1.18.0" computer: dependency: "direct main" description: @@ -350,18 +350,18 @@ packages: dependency: transitive description: name: coverage - sha256: "2fb815080e44a09b85e0f2ca8a820b15053982b2e714b59267719e8a9ff17097" + sha256: "595a29b55ce82d53398e1bcc2cba525d7bd7c59faeb2d2540e9d42c390cfeeeb" url: "https://pub.dev" source: hosted - version: "1.6.3" + version: "1.6.4" cross_file: dependency: "direct main" description: name: cross_file - sha256: "2f9d2cbccb76127ba28528cb3ae2c2326a122446a83de5a056aaa3880d3882c5" + sha256: fedaadfa3a6996f75211d835aaeb8fede285dae94262485698afd832371b9a5e url: "https://pub.dev" source: hosted - version: "0.3.3+7" + version: "0.3.3+8" crypto: dependency: "direct main" description: @@ -422,10 +422,10 @@ packages: dependency: "direct main" description: name: device_info_plus - sha256: "0042cb3b2a76413ea5f8a2b40cec2a33e01d0c937e91f0f7c211fde4f7739ba6" + sha256: "77f757b789ff68e4eaf9c56d1752309bd9f7ad557cb105b938a7f8eb89e59110" url: "https://pub.dev" source: hosted - version: "9.1.1" + version: "9.1.2" device_info_plus_platform_interface: dependency: transitive description: @@ -518,18 +518,18 @@ packages: dependency: "direct main" description: name: extended_image - sha256: b4d72a27851751cfadaf048936d42939db7cd66c08fdcfe651eeaa1179714ee6 + sha256: d7f091d068fcac7246c4b22a84b8dac59a62e04d29a5c172710c696e67a22f94 url: "https://pub.dev" source: hosted - version: "8.1.1" + version: "8.2.0" extended_image_library: dependency: transitive description: name: extended_image_library - sha256: "8bf87c0b14dcb59200c923a9a3952304e4732a0901e40811428834ef39018ee1" + sha256: "9b55fc5ebc65fad984de66b8f177a1bef2a84d79203c9c213f75ff83c2c29edd" url: "https://pub.dev" source: hosted - version: "3.6.0" + version: "4.0.1" fade_indexed_stack: dependency: "direct main" description: @@ -591,10 +591,10 @@ packages: dependency: "direct main" description: name: firebase_core - sha256: "96607c0e829a581c2a483c658f04e8b159964c3bae2730f73297070bc85d40bb" + sha256: "53316975310c8af75a96e365f9fccb67d1c544ef0acdbf0d88bbe30eedd1c4f9" url: "https://pub.dev" source: hosted - version: "2.24.2" + version: "2.27.0" firebase_core_platform_interface: dependency: transitive description: @@ -607,34 +607,34 @@ packages: dependency: transitive description: name: firebase_core_web - sha256: d585bdf3c656c3f7821ba1bd44da5f13365d22fcecaf5eb75c4295246aaa83c0 + sha256: c8e1d59385eee98de63c92f961d2a7062c5d9a65e7f45bdc7f1b0b205aab2492 url: "https://pub.dev" source: hosted - version: "2.10.0" + version: "2.11.5" firebase_messaging: dependency: "direct main" description: name: firebase_messaging - sha256: "980259425fa5e2afc03e533f33723335731d21a56fd255611083bceebf4373a8" + sha256: e41586e0fd04fe9a40424f8b0053d0832e6d04f49e020cdaf9919209a28497e9 url: "https://pub.dev" source: hosted - version: "14.7.10" + version: "14.7.19" firebase_messaging_platform_interface: dependency: transitive description: name: firebase_messaging_platform_interface - sha256: "54e283a0e41d81d854636ad0dad73066adc53407a60a7c3189c9656e2f1b6107" + sha256: f7a9d74ff7fc588a924f6b2eaeaa148b0db521b13a9db55f6ad45864fa98c06e url: "https://pub.dev" source: hosted - version: "4.5.18" + version: "4.5.27" firebase_messaging_web: dependency: transitive description: name: firebase_messaging_web - sha256: "90dc7ed885e90a24bb0e56d661d4d2b5f84429697fd2cbb9e5890a0ca370e6f4" + sha256: fc21e771166860c55b103701c5ac7cdb2eec28897b97c42e6e5703cbedf9e02e url: "https://pub.dev" source: hosted - version: "3.5.18" + version: "3.6.8" fixnum: dependency: transitive description: @@ -660,10 +660,10 @@ packages: dependency: "direct main" description: name: flutter_animate - sha256: cabe33af6201144be052352d53572a1b8a4f5782b46080be7520d95abe763715 + sha256: "7c8a6594a9252dad30cc2ef16e33270b6248c4dedc3b3d06c86c4f3f4dc05ae5" url: "https://pub.dev" source: hosted - version: "4.4.1" + version: "4.5.0" flutter_cache_manager: dependency: "direct main" description: @@ -798,10 +798,10 @@ packages: dependency: "direct main" description: name: flutter_native_splash - sha256: "17d9671396fb8ec45ad10f4a975eb8a0f70bedf0fdaf0720b31ea9de6da8c4da" + sha256: "558f10070f03ee71f850a78f7136ab239a67636a294a44a06b6b7345178edb1e" url: "https://pub.dev" source: hosted - version: "2.3.7" + version: "2.3.10" flutter_password_strength: dependency: "direct main" description: @@ -866,6 +866,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" + flutter_shaders: + dependency: transitive + description: + name: flutter_shaders + sha256: "02750b545c01ff4d8e9bbe8f27a7731aa3778402506c67daa1de7f5fc3f4befe" + url: "https://pub.dev" + source: hosted + version: "0.1.2" flutter_sodium: dependency: "direct main" description: @@ -878,10 +886,10 @@ packages: dependency: transitive description: name: flutter_spinkit - sha256: b39c753e909d4796906c5696a14daf33639a76e017136c8d82bf3e620ce5bb8e + sha256: d2696eed13732831414595b98863260e33e8882fc069ee80ec35d4ac9ddb0472 url: "https://pub.dev" source: hosted - version: "5.2.0" + version: "5.2.1" flutter_staggered_grid_view: dependency: "direct main" description: @@ -912,10 +920,10 @@ packages: dependency: "direct dev" description: name: freezed - sha256: "6c5031daae12c7072b3a87eff98983076434b4889ef2a44384d0cae3f82372ba" + sha256: "57247f692f35f068cae297549a46a9a097100685c6780fe67177503eea5ed4e5" url: "https://pub.dev" source: hosted - version: "2.4.6" + version: "2.4.7" freezed_annotation: dependency: "direct main" description: @@ -974,7 +982,7 @@ packages: description: path: "." ref: main - resolved-ref: "49158ce4a517e87817dc84c6b96c00639281229a" + resolved-ref: "19b5389186b8b96a0c11c29674cf15cbd7855f6b" url: "https://github.com/ente-io/FlutterHomeWidget" source: git version: "0.4.1" @@ -998,10 +1006,10 @@ packages: dependency: "direct main" description: name: http - sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" + sha256: a2bbf9d017fcced29139daa8ed2bba4ece450ab222871df93ca9eec6f80c34ba url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.2.0" http_client_helper: dependency: transitive description: @@ -1030,18 +1038,18 @@ packages: dependency: "direct main" description: name: image - sha256: "004a2e90ce080f8627b5a04aecb4cdfac87d2c3f3b520aa291260be5a32c033d" + sha256: "4c68bfd5ae83e700b5204c1e74451e7bf3cf750e6843c6e158289cf56bda018e" url: "https://pub.dev" source: hosted - version: "4.1.4" + version: "4.1.7" image_editor: dependency: "direct main" description: name: image_editor - sha256: "9877a057b0cd2fafcd9a3dce5279948bd850d53ce76231a83c9678a2c9f186e9" + sha256: "6401a431ef1e988e35a8b19ff02cb7d31bd881fd7db0d39261ac8236683ef1c1" url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.0" image_editor_common: dependency: transitive description: @@ -1050,6 +1058,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" + image_editor_ohos: + dependency: transitive + description: + name: image_editor_ohos + sha256: "2f6ae408f7879387a64dcac096ad9db0dc5e0985f6106d6f2a9b969c8932b09c" + url: "https://pub.dev" + source: hosted + version: "0.0.5" image_editor_platform_interface: dependency: transitive description: @@ -1070,10 +1086,10 @@ packages: dependency: transitive description: name: in_app_purchase_android - sha256: "28164faac635a6cc357c96f47813e675eec7622a8f41e829b501573dbbce2cce" + sha256: "996da8020228658c71eddb30f2a2e723d87d5eef77d8007f9206969605e8f803" url: "https://pub.dev" source: hosted - version: "0.3.0+17" + version: "0.3.2" in_app_purchase_platform_interface: dependency: transitive description: @@ -1163,10 +1179,10 @@ packages: dependency: "direct main" description: name: latlong2 - sha256: "18712164760cee655bc790122b0fd8f3d5b3c36da2cb7bf94b68a197fbb0811b" + sha256: "98227922caf49e6056f91b6c56945ea1c7b166f28ffcd5fb8e72fc0b453cc8fe" url: "https://pub.dev" source: hosted - version: "0.9.0" + version: "0.9.1" like_button: dependency: "direct main" description: @@ -1211,10 +1227,10 @@ packages: dependency: "direct main" description: name: local_auth_android - sha256: "54e9c35ce52c06333355ab0d0f41e4c06dbca354b23426765ba41dfb1de27598" + sha256: "3bcd732dda7c75fcb7ddaef12e131230f53dcc8c00790d0d6efb3aa0fbbeda57" url: "https://pub.dev" source: hosted - version: "1.0.36" + version: "1.0.37" local_auth_ios: dependency: "direct main" description: @@ -1355,10 +1371,10 @@ packages: dependency: transitive description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" mgrs_dart: dependency: transitive description: @@ -1371,10 +1387,10 @@ packages: dependency: transitive description: name: mime - sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2" url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "1.0.5" modal_bottom_sheet: dependency: "direct main" description: @@ -1582,18 +1598,26 @@ packages: dependency: transitive description: name: petitparser - sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 + sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 url: "https://pub.dev" source: hosted - version: "5.4.0" + version: "6.0.2" photo_manager: dependency: "direct main" description: name: photo_manager - sha256: "2d698826421ebd045ecc0df60422e9dd24bd22b178310b68444385f783735b55" + sha256: df594f989f0c31cdb3ed48f3d49cb9ffadf11cc3700d2c3460b1912c93432621 url: "https://pub.dev" source: hosted - version: "2.8.1" + version: "3.0.0" + photo_manager_image_provider: + dependency: transitive + description: + name: photo_manager_image_provider + sha256: "38ef1023dc11de3a8669f16e7c981673b3c5cfee715d17120f4b87daa2cdd0af" + url: "https://pub.dev" + source: hosted + version: "2.1.1" photo_view: dependency: "direct main" description: @@ -1614,10 +1638,10 @@ packages: dependency: transitive description: name: platform - sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + sha256: ae68c7bfcd7383af3629daafb32fb4e8681c7154428da4febcff06200585f102 url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.2" plugin_platform_interface: dependency: transitive description: @@ -1678,10 +1702,10 @@ packages: dependency: "direct main" description: name: provider - sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096" + sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c url: "https://pub.dev" source: hosted - version: "6.1.1" + version: "6.1.2" pub_semver: dependency: transitive description: @@ -1790,18 +1814,18 @@ packages: dependency: "direct main" description: name: sentry - sha256: "5686ed515bb620dc52b4ae99a6586fe720d443591183cf1f620ec5d1f0eec100" + sha256: a460aa48568d47140dd0557410b624d344ffb8c05555107ac65035c1097cf1ad url: "https://pub.dev" source: hosted - version: "7.15.0" + version: "7.18.0" sentry_flutter: dependency: "direct main" description: name: sentry_flutter - sha256: "505dec3b6810562785d2c34ae871c73ff2cba6cf436c32c188f0464df226ba8f" + sha256: "3d0d1d4e0e407d276ae8128d123263ccbc37e988bae906765efd6f37d544f4c6" url: "https://pub.dev" source: hosted - version: "7.15.0" + version: "7.18.0" share_plus: dependency: "direct main" description: @@ -1830,10 +1854,10 @@ packages: dependency: transitive description: name: share_plus_platform_interface - sha256: df08bc3a07d01f5ea47b45d03ffcba1fa9cd5370fb44b3f38c70e42cced0f956 + sha256: "251eb156a8b5fa9ce033747d73535bf53911071f8d3b6f4f0b578505ce0d4496" url: "https://pub.dev" source: hosted - version: "3.3.1" + version: "3.4.0" share_plus_web: dependency: transitive description: @@ -1894,10 +1918,10 @@ packages: dependency: transitive description: name: shared_preferences_web - sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf + sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.2" shared_preferences_windows: dependency: transitive description: @@ -2019,26 +2043,26 @@ packages: dependency: "direct main" description: name: sqlite3 - sha256: db65233e6b99e99b2548932f55a987961bc06d82a31a0665451fa0b4fff4c3fb + sha256: "072128763f1547e3e9b4735ce846bfd226d68019ccda54db4cd427b12dfdedc9" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.4.0" sqlite3_flutter_libs: dependency: "direct main" description: name: sqlite3_flutter_libs - sha256: "90963b515721d6a71e96f438175cf43c979493ed14822860a300b69694c74eb6" + sha256: d6c31c8511c441d1f12f20b607343df1afe4eddf24a1cf85021677c8eea26060 url: "https://pub.dev" source: hosted - version: "0.5.19+1" + version: "0.5.20" stack_trace: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.11.1" step_progress_indicator: dependency: "direct main" description: @@ -2051,10 +2075,10 @@ packages: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" stream_transform: dependency: transitive description: @@ -2123,26 +2147,26 @@ packages: dependency: "direct dev" description: name: test - sha256: "13b41f318e2a5751c3169137103b60c584297353d4b1761b66029bae6411fe46" + sha256: a1f7595805820fcc05e5c52e3a231aedd0b72972cb333e8c738a8b1239448b6f url: "https://pub.dev" source: hosted - version: "1.24.3" + version: "1.24.9" test_api: dependency: transitive description: name: test_api - sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" url: "https://pub.dev" source: hosted - version: "0.6.0" + version: "0.6.1" test_core: dependency: transitive description: name: test_core - sha256: "99806e9e6d95c7b059b7a0fc08f07fc53fabe54a829497f0d9676299f1e8637e" + sha256: a757b14fc47507060a162cc2530d9a4a2f92f5100a952c7443b5cad5ef5b106a url: "https://pub.dev" source: hosted - version: "0.5.3" + version: "0.5.9" time: dependency: transitive description: @@ -2243,18 +2267,18 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: c512655380d241a337521703af62d2c122bf7b77a46ff7dd750092aa9433499c + sha256: "0ecc004c62fd3ed36a2ffcbe0dd9700aee63bd7532d0b642a488b1ec310f492e" url: "https://pub.dev" source: hosted - version: "6.2.4" + version: "6.2.5" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "507dc655b1d9cb5ebc756032eb785f114e415f91557b73bf60b7e201dfedeb2f" + sha256: d4ed0711849dd8e33eb2dd69c25db0d0d3fdc37e0a62e629fe32f57a22db2745 url: "https://pub.dev" source: hosted - version: "6.2.2" + version: "6.3.0" url_launcher_ios: dependency: transitive description: @@ -2283,18 +2307,18 @@ packages: dependency: transitive description: name: url_launcher_platform_interface - sha256: a932c3a8082e118f80a475ce692fde89dc20fddb24c57360b96bc56f7035de1f + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" url_launcher_web: dependency: transitive description: name: url_launcher_web - sha256: "7fd2f55fe86cea2897b963e864dc01a7eb0719ecc65fcef4c1cc3d686d718bb2" + sha256: fff0932192afeedf63cdd50ecbb1bc825d31aed259f02bb8dba0f3b729a5e88b url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.3" url_launcher_windows: dependency: transitive description: @@ -2332,18 +2356,18 @@ packages: dependency: transitive description: name: video_player_android - sha256: "7f8f25d7ad56819a82b2948357f3c3af071f6a678db33833b26ec36bbc221316" + sha256: "4dd9b8b86d70d65eecf3dcabfcdfbb9c9115d244d022654aba49a00336d540c2" url: "https://pub.dev" source: hosted - version: "2.4.11" + version: "2.4.12" video_player_avfoundation: dependency: transitive description: name: video_player_avfoundation - sha256: bc923884640d6dc403050586eb40713cdb8d1d84e6886d8aca50ab04c59124c2 + sha256: "309e3962795e761be010869bae65c0b0e45b5230c5cee1bec72197ca7db040ed" url: "https://pub.dev" source: hosted - version: "2.5.2" + version: "2.5.6" video_player_platform_interface: dependency: transitive description: @@ -2380,10 +2404,10 @@ packages: dependency: transitive description: name: vm_service - sha256: c620a6f783fa22436da68e42db7ebbf18b8c44b9a46ab911f666ff09ffd9153f + sha256: c538be99af830f478718b51630ec1b6bee5e74e52c8a802d328d9e71d35d2583 url: "https://pub.dev" source: hosted - version: "11.7.1" + version: "11.10.0" volume_controller: dependency: transitive description: @@ -2428,10 +2452,10 @@ packages: dependency: transitive description: name: web - sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 url: "https://pub.dev" source: hosted - version: "0.1.4-beta" + version: "0.3.0" web_socket_channel: dependency: transitive description: @@ -2460,10 +2484,10 @@ packages: dependency: "direct main" description: name: wechat_assets_picker - sha256: f78c7797dc88e3c9170d318acc9f535ca104ab648cc69ab3b7745f1ceac29910 + sha256: "9934724a45fdb2b12e332d8190c58713e6675c37c630d53608e0f50167215c9f" url: "https://pub.dev" source: hosted - version: "8.8.1+1" + version: "8.9.0-dev.1" widgets_to_image: dependency: "direct main" description: @@ -2476,10 +2500,10 @@ packages: dependency: transitive description: name: win32 - sha256: b0f37db61ba2f2e9b7a78a1caece0052564d1bc70668156cf3a29d676fe4e574 + sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8" url: "https://pub.dev" source: hosted - version: "5.1.1" + version: "5.2.0" win32_registry: dependency: transitive description: @@ -2508,10 +2532,10 @@ packages: dependency: transitive description: name: xml - sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" + sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 url: "https://pub.dev" source: hosted - version: "6.3.0" + version: "6.5.0" xmlstream: dependency: transitive description: @@ -2537,5 +2561,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.1.3 <4.0.0" - flutter: ">=3.13.0" + dart: ">=3.2.0 <4.0.0" + flutter: ">=3.16.0" diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index 8d65409dcb..8306bc5a79 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -134,7 +134,7 @@ dependencies: path: #dart path_provider: ^2.1.1 pedantic: ^1.9.2 - photo_manager: ^2.8.1 + photo_manager: ^3.0.0 photo_view: ^0.14.0 pinput: ^1.2.2 pointycastle: ^3.7.3 From fa304aa8ccb6ca4f81ea0adb25a1ae72ff2270e0 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Thu, 28 Mar 2024 16:56:54 +0530 Subject: [PATCH 03/84] upgrade flutter version --- mobile/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/README.md b/mobile/README.md index f2889a9ce1..b9fcaff600 100644 --- a/mobile/README.md +++ b/mobile/README.md @@ -46,7 +46,7 @@ You can alternatively install the build from PlayStore or F-Droid. ## 🧑‍💻 Building from source -1. [Install Flutter v3.16.0](https://flutter.dev/docs/get-started/install). +1. [Install Flutter v3.16.9](https://flutter.dev/docs/get-started/install). 2. Pull in all submodules with `git submodule update --init --recursive` From 9f22882d8d24ce29a166cb16c641dfead273475e Mon Sep 17 00:00:00 2001 From: ashilkn Date: Thu, 28 Mar 2024 17:18:12 +0530 Subject: [PATCH 04/84] override ffi dependency version to fix build failing after running flutter pub upgrade command --- mobile/pubspec.lock | 28 ++++++++++++++++++---------- mobile/pubspec.yaml | 9 ++++----- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index 41c30e2ce8..e170a2bb3a 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -1102,10 +1102,10 @@ packages: dependency: transitive description: name: in_app_purchase_storekit - sha256: c4b17a7f2ca8ddc7fd7996a8c32a3af6beddf91d651997c8675a5f23c103c9bc + sha256: e0f860e760488dbd666e0f27e239d128cba744607fc62434dc76c19d1c292439 url: "https://pub.dev" source: hosted - version: "0.3.8+1" + version: "0.3.13+1" integration_test: dependency: "direct dev" description: flutter @@ -1219,10 +1219,10 @@ packages: dependency: "direct main" description: name: local_auth - sha256: "27679ed8e0d7daab2357db6bb7076359e083a56b295c0c59723845301da6aed9" + sha256: "280421b416b32de31405b0a25c3bd42dfcef2538dfbb20c03019e02a5ed55ed0" url: "https://pub.dev" source: hosted - version: "2.1.8" + version: "2.2.0" local_auth_android: dependency: "direct main" description: @@ -1231,14 +1231,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.37" + local_auth_darwin: + dependency: transitive + description: + name: local_auth_darwin + sha256: "33381a15b0de2279523eca694089393bb146baebdce72a404555d03174ebc1e9" + url: "https://pub.dev" + source: hosted + version: "1.2.2" local_auth_ios: dependency: "direct main" description: name: local_auth_ios - sha256: eb283b530029b334698918f1e282d4483737cbca972ff21b9193be3d6de8e2b8 + sha256: "6dde47dc852bc0c8343cb58e66a46efb16b62eddf389ce103d4dacb0c6c40c71" url: "https://pub.dev" source: hosted - version: "1.1.6" + version: "1.1.7" local_auth_platform_interface: dependency: transitive description: @@ -2283,10 +2291,10 @@ packages: dependency: transitive description: name: url_launcher_ios - sha256: "75bb6fe3f60070407704282a2d295630cab232991eb52542b18347a8a941df03" + sha256: "9149d493b075ed740901f3ee844a38a00b33116c7c5c10d7fb27df8987fb51d5" url: "https://pub.dev" source: hosted - version: "6.2.4" + version: "6.2.5" url_launcher_linux: dependency: transitive description: @@ -2561,5 +2569,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.2.0 <4.0.0" - flutter: ">=3.16.0" + dart: ">=3.2.3 <4.0.0" + flutter: ">=3.16.6" diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index 8306bc5a79..8d39f93781 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -60,7 +60,6 @@ dependencies: extended_image: ^8.1.1 fade_indexed_stack: ^0.2.2 fast_base58: ^0.2.1 - figma_squircle: ^0.5.3 file_saver: # Use forked version till this PR is merged: https://github.com/incrediblezayed/file_saver/pull/87 @@ -177,10 +176,10 @@ dependencies: dependency_overrides: connectivity_plus: ^4.0.0 - # current fork of tfite_flutter_helper depends on ffi: ^1.x.x - # but we need ffi: ^2.0.1 for newer packages. The original tfite_flutter_helper - # - ffi: ^2.1.0 + + #Remove this after upgrading to flutter v3.19x + #Build fails when resolving to latest version of ffi on flutter v3.16.x + ffi: 2.1.0 video_player: git: url: https://github.com/ente-io/packages.git From 4c73fb7374fc5921f6ec0e2bea1dfa25eb6668d9 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Thu, 28 Mar 2024 18:22:38 +0530 Subject: [PATCH 05/84] Specify color for dividers to keep it same after flutter upgrade New material theme has a different default colour for dividers --- mobile/lib/ui/account/email_entry_page.dart | 5 ++- mobile/lib/ui/account/login_page.dart | 6 ++- .../account/login_pwd_verification_page.dart | 5 ++- .../lib/ui/account/ott_verification_page.dart | 44 ++++++++++--------- .../lib/ui/account/password_reentry_page.dart | 6 ++- mobile/lib/ui/account/recovery_page.dart | 6 ++- .../request_pwd_verification_page.dart | 5 ++- mobile/lib/ui/account/sessions_page.dart | 5 ++- mobile/lib/ui/home/status_bar_widget.dart | 4 +- mobile/lib/ui/tabs/user_collections_tab.dart | 7 ++- 10 files changed, 59 insertions(+), 34 deletions(-) diff --git a/mobile/lib/ui/account/email_entry_page.dart b/mobile/lib/ui/account/email_entry_page.dart index e46e8fa7e5..888542f160 100644 --- a/mobile/lib/ui/account/email_entry_page.dart +++ b/mobile/lib/ui/account/email_entry_page.dart @@ -375,7 +375,10 @@ class _EmailEntryPageState extends State { textInputAction: TextInputAction.next, ), ), - const Divider(thickness: 1), + Divider( + thickness: 1, + color: getEnteColorScheme(context).strokeFaint, + ), const SizedBox(height: 12), _getAgreement(), const SizedBox(height: 40), diff --git a/mobile/lib/ui/account/login_page.dart b/mobile/lib/ui/account/login_page.dart index 2d620ecb2a..546a5f3b92 100644 --- a/mobile/lib/ui/account/login_page.dart +++ b/mobile/lib/ui/account/login_page.dart @@ -8,6 +8,7 @@ import "package:photos/generated/l10n.dart"; import "package:photos/l10n/l10n.dart"; import "package:photos/models/api/user/srp.dart"; import 'package:photos/services/user_service.dart'; +import "package:photos/theme/ente_theme.dart"; import "package:photos/ui/account/login_pwd_verification_page.dart"; import 'package:photos/ui/common/dynamic_fab.dart'; import 'package:photos/ui/common/web_page.dart'; @@ -159,10 +160,11 @@ class _LoginPageState extends State { autofocus: true, ), ), - const Padding( - padding: EdgeInsets.symmetric(vertical: 18), + Padding( + padding: const EdgeInsets.symmetric(vertical: 18), child: Divider( thickness: 1, + color: getEnteColorScheme(context).strokeFaint, ), ), Padding( diff --git a/mobile/lib/ui/account/login_pwd_verification_page.dart b/mobile/lib/ui/account/login_pwd_verification_page.dart index a253b1585a..884a5a4c7e 100644 --- a/mobile/lib/ui/account/login_pwd_verification_page.dart +++ b/mobile/lib/ui/account/login_pwd_verification_page.dart @@ -282,10 +282,11 @@ class _LoginPasswordVerificationPageState }, ), ), - const Padding( - padding: EdgeInsets.symmetric(vertical: 18), + Padding( + padding: const EdgeInsets.symmetric(vertical: 18), child: Divider( thickness: 1, + color: getEnteColorScheme(context).strokeFaint, ), ), Padding( diff --git a/mobile/lib/ui/account/ott_verification_page.dart b/mobile/lib/ui/account/ott_verification_page.dart index 77b48d3600..9dee22e160 100644 --- a/mobile/lib/ui/account/ott_verification_page.dart +++ b/mobile/lib/ui/account/ott_verification_page.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:photos/ente_theme_data.dart'; import "package:photos/generated/l10n.dart"; import 'package:photos/services/user_service.dart'; +import "package:photos/theme/ente_theme.dart"; import 'package:photos/ui/common/dynamic_fab.dart'; import 'package:step_progress_indicator/step_progress_indicator.dart'; import "package:styled_text/styled_text.dart"; @@ -16,7 +17,7 @@ class OTTVerificationPage extends StatefulWidget { this.email, { this.isChangeEmail = false, this.isCreateAccountScreen = false, - this.isResetPasswordScreen = false, + this.isResetPasswordScreen = false, Key? key, }) : super(key: key); @@ -78,9 +79,11 @@ class _OTTVerificationPageState extends State { _verificationCodeController.text, ); } else { - UserService.instance - .verifyEmail(context, _verificationCodeController.text, - isResettingPasswordScreen: widget.isResetPasswordScreen,); + UserService.instance.verifyEmail( + context, + _verificationCodeController.text, + isResettingPasswordScreen: widget.isResetPasswordScreen, + ); } FocusScope.of(context).unfocus(); }, @@ -130,21 +133,21 @@ class _OTTVerificationPageState extends State { }, ), ), - widget.isResetPasswordScreen ? - Text( - S.of(context).toResetVerifyEmail, - style: Theme.of(context) - .textTheme - .titleMedium! - .copyWith(fontSize: 14), - ): - Text( - S.of(context).checkInboxAndSpamFolder, - style: Theme.of(context) - .textTheme - .titleMedium! - .copyWith(fontSize: 14), - ), + widget.isResetPasswordScreen + ? Text( + S.of(context).toResetVerifyEmail, + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith(fontSize: 14), + ) + : Text( + S.of(context).checkInboxAndSpamFolder, + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith(fontSize: 14), + ), ], ), ), @@ -178,8 +181,9 @@ class _OTTVerificationPageState extends State { }, ), ), - const Divider( + Divider( thickness: 1, + color: getEnteColorScheme(context).strokeFaint, ), Padding( padding: const EdgeInsets.all(20), diff --git a/mobile/lib/ui/account/password_reentry_page.dart b/mobile/lib/ui/account/password_reentry_page.dart index 1b240134f9..cfbc30c10f 100644 --- a/mobile/lib/ui/account/password_reentry_page.dart +++ b/mobile/lib/ui/account/password_reentry_page.dart @@ -9,6 +9,7 @@ import 'package:photos/core/event_bus.dart'; import 'package:photos/events/subscription_purchased_event.dart'; import "package:photos/generated/l10n.dart"; import "package:photos/services/user_service.dart"; +import "package:photos/theme/ente_theme.dart"; import 'package:photos/ui/account/recovery_page.dart'; import 'package:photos/ui/common/dynamic_fab.dart'; import 'package:photos/ui/components/buttons/button_widget.dart'; @@ -257,10 +258,11 @@ class _PasswordReentryPageState extends State { }, ), ), - const Padding( - padding: EdgeInsets.symmetric(vertical: 18), + Padding( + padding: const EdgeInsets.symmetric(vertical: 18), child: Divider( thickness: 1, + color: getEnteColorScheme(context).strokeFaint, ), ), Padding( diff --git a/mobile/lib/ui/account/recovery_page.dart b/mobile/lib/ui/account/recovery_page.dart index 97d3bfc335..d5c651f92f 100644 --- a/mobile/lib/ui/account/recovery_page.dart +++ b/mobile/lib/ui/account/recovery_page.dart @@ -3,6 +3,7 @@ import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:photos/core/configuration.dart'; import "package:photos/generated/l10n.dart"; +import "package:photos/theme/ente_theme.dart"; import 'package:photos/ui/account/password_entry_page.dart'; import 'package:photos/ui/common/dynamic_fab.dart'; import 'package:photos/utils/dialog_util.dart'; @@ -123,10 +124,11 @@ class _RecoveryPageState extends State { }, ), ), - const Padding( - padding: EdgeInsets.symmetric(vertical: 18), + Padding( + padding: const EdgeInsets.symmetric(vertical: 18), child: Divider( thickness: 1, + color: getEnteColorScheme(context).strokeFaint, ), ), Row( diff --git a/mobile/lib/ui/account/request_pwd_verification_page.dart b/mobile/lib/ui/account/request_pwd_verification_page.dart index 67908f734b..9da169dea6 100644 --- a/mobile/lib/ui/account/request_pwd_verification_page.dart +++ b/mobile/lib/ui/account/request_pwd_verification_page.dart @@ -210,10 +210,11 @@ class _RequestPasswordVerificationPageState }, ), ), - const Padding( - padding: EdgeInsets.symmetric(vertical: 18), + Padding( + padding: const EdgeInsets.symmetric(vertical: 18), child: Divider( thickness: 1, + color: getEnteColorScheme(context).strokeFaint, ), ), ], diff --git a/mobile/lib/ui/account/sessions_page.dart b/mobile/lib/ui/account/sessions_page.dart index e4468c5e24..603d951353 100644 --- a/mobile/lib/ui/account/sessions_page.dart +++ b/mobile/lib/ui/account/sessions_page.dart @@ -5,6 +5,7 @@ import 'package:photos/ente_theme_data.dart'; import "package:photos/generated/l10n.dart"; import 'package:photos/models/sessions.dart'; import 'package:photos/services/user_service.dart'; +import "package:photos/theme/ente_theme.dart"; import 'package:photos/ui/common/loading_widget.dart'; import "package:photos/utils/date_time_util.dart"; import 'package:photos/utils/dialog_util.dart'; @@ -106,7 +107,9 @@ class _SessionsPageState extends State { ), ), ), - const Divider(), + Divider( + color: getEnteColorScheme(context).strokeFaint, + ), ], ); } diff --git a/mobile/lib/ui/home/status_bar_widget.dart b/mobile/lib/ui/home/status_bar_widget.dart index e730fbd639..8df1a90242 100644 --- a/mobile/lib/ui/home/status_bar_widget.dart +++ b/mobile/lib/ui/home/status_bar_widget.dart @@ -10,6 +10,7 @@ import 'package:photos/events/sync_status_update_event.dart'; import "package:photos/generated/l10n.dart"; import 'package:photos/services/sync_service.dart'; import 'package:photos/services/user_remote_flag_service.dart'; +import "package:photos/theme/ente_theme.dart"; import 'package:photos/theme/text_style.dart'; import 'package:photos/ui/account/verify_recovery_page.dart'; import 'package:photos/ui/components/home_header_widget.dart'; @@ -93,8 +94,9 @@ class _StatusBarWidgetState extends State { : const Text("ente", style: brandStyleMedium), ), _showErrorBanner - ? const Divider( + ? Divider( height: 8, + color: getEnteColorScheme(context).strokeFaint, ) : const SizedBox.shrink(), _showErrorBanner diff --git a/mobile/lib/ui/tabs/user_collections_tab.dart b/mobile/lib/ui/tabs/user_collections_tab.dart index e5eab83178..93e5b19822 100644 --- a/mobile/lib/ui/tabs/user_collections_tab.dart +++ b/mobile/lib/ui/tabs/user_collections_tab.dart @@ -10,6 +10,7 @@ import 'package:photos/events/user_logged_out_event.dart'; import "package:photos/generated/l10n.dart"; import 'package:photos/models/collection/collection.dart'; import 'package:photos/services/collections_service.dart'; +import "package:photos/theme/ente_theme.dart"; import "package:photos/ui/collections/button/archived_button.dart"; import "package:photos/ui/collections/button/hidden_button.dart"; import "package:photos/ui/collections/button/trash_button.dart"; @@ -184,7 +185,11 @@ class _UserCollectionsTabState extends State ), ) : const SliverToBoxAdapter(child: SizedBox.shrink()), - const SliverToBoxAdapter(child: Divider()), + SliverToBoxAdapter( + child: Divider( + color: getEnteColorScheme(context).strokeFaint, + ), + ), const SliverToBoxAdapter(child: SizedBox(height: 12)), SliverToBoxAdapter( child: Padding( From b976d30ab294fe75491b68460404dabd80bc1c5f Mon Sep 17 00:00:00 2001 From: ashilkn Date: Thu, 28 Mar 2024 20:37:27 +0530 Subject: [PATCH 06/84] fix colours in new material 3 toggle switch --- mobile/lib/ui/components/toggle_switch_widget.dart | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/mobile/lib/ui/components/toggle_switch_widget.dart b/mobile/lib/ui/components/toggle_switch_widget.dart index 33477ae9b3..9d1de15395 100644 --- a/mobile/lib/ui/components/toggle_switch_widget.dart +++ b/mobile/lib/ui/components/toggle_switch_widget.dart @@ -25,8 +25,8 @@ class _ToggleSwitchWidgetState extends State { @override void initState() { - toggleValue = widget.value.call(); super.initState(); + toggleValue = widget.value.call(); } @override @@ -50,8 +50,13 @@ class _ToggleSwitchWidgetState extends State { child: FittedBox( fit: BoxFit.contain, child: Switch.adaptive( - activeColor: enteColorScheme.primary400, - inactiveTrackColor: enteColorScheme.fillMuted, + inactiveTrackColor: Colors.transparent, + activeTrackColor: enteColorScheme.primary500, + activeColor: Colors.white, + inactiveThumbColor: enteColorScheme.primary500, + trackOutlineColor: MaterialStateColor.resolveWith( + (states) => enteColorScheme.primary500, + ), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, value: toggleValue ?? false, onChanged: (negationOfToggleValue) async { From 0e9db0828fff8ba64fcef0d06db9e7ca66825443 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Wed, 10 Apr 2024 16:51:28 +0530 Subject: [PATCH 07/84] pub upgrade changes --- mobile/pubspec.lock | 72 +++++++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 32 deletions(-) diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index 716614997b..ab3ca70204 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -189,10 +189,10 @@ packages: dependency: "direct dev" description: name: build_runner - sha256: "581bacf68f89ec8792f5e5a0b2c4decd1c948e97ce659dc783688c8a88fbec21" + sha256: "3ac61a79bfb6f6cc11f693591063a7f19a7af628dc52f141743edac5c16e8c22" url: "https://pub.dev" source: hosted - version: "2.4.8" + version: "2.4.9" build_runner_core: dependency: transitive description: @@ -213,10 +213,10 @@ packages: dependency: transitive description: name: built_value - sha256: fedde275e0a6b798c3296963c5cd224e3e1b55d0e478d5b7e65e6b540f363a0e + sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb url: "https://pub.dev" source: hosted - version: "8.9.1" + version: "8.9.2" cached_network_image: dependency: "direct main" description: @@ -814,10 +814,10 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: b068ffc46f82a55844acfa4fdbb61fad72fa2aef0905548419d97f0f95c456da + sha256: "592dc01a18961a51c24ae5d963b724b2b7fa4a95c100fe8eb6ca8a5a4732cadf" url: "https://pub.dev" source: hosted - version: "2.0.17" + version: "2.0.18" flutter_secure_storage: dependency: "direct main" description: @@ -920,10 +920,10 @@ packages: dependency: "direct dev" description: name: freezed - sha256: "57247f692f35f068cae297549a46a9a097100685c6780fe67177503eea5ed4e5" + sha256: "91bce569d4805ea5bad6619a3e8690df8ad062a235165af4c0c5d928dda15eaf" url: "https://pub.dev" source: hosted - version: "2.4.7" + version: "2.5.1" freezed_annotation: dependency: "direct main" description: @@ -1061,10 +1061,10 @@ packages: dependency: transitive description: name: image_editor_ohos - sha256: "2f6ae408f7879387a64dcac096ad9db0dc5e0985f6106d6f2a9b969c8932b09c" + sha256: "55c08871814efdd19b3927327b5913649dd1ea36e0a83aa77ab668dad3160dcc" url: "https://pub.dev" source: hosted - version: "0.0.5" + version: "0.0.6" image_editor_platform_interface: dependency: transitive description: @@ -1085,10 +1085,10 @@ packages: dependency: transitive description: name: in_app_purchase_android - sha256: "996da8020228658c71eddb30f2a2e723d87d5eef77d8007f9206969605e8f803" + sha256: "6863bf74335ccbd80829e8c3d16176f90794f0f8593a4505a7ab79d17334a0bf" url: "https://pub.dev" source: hosted - version: "0.3.2" + version: "0.3.3" in_app_purchase_platform_interface: dependency: transitive description: @@ -1557,10 +1557,10 @@ packages: dependency: transitive description: name: path_provider_android - sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668" + sha256: "51f0d2c554cfbc9d6a312ab35152fc77e2f0b758ce9f1a444a3a1e5b8f3c6b7f" url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.2.3" path_provider_foundation: dependency: transitive description: @@ -1605,42 +1605,50 @@ packages: dependency: "direct main" description: name: permission_handler - sha256: "284a66179cabdf942f838543e10413246f06424d960c92ba95c84439154fcac8" + sha256: "18bf33f7fefbd812f37e72091a15575e72d5318854877e0e4035a24ac1113ecb" url: "https://pub.dev" source: hosted - version: "11.0.1" + version: "11.3.1" permission_handler_android: dependency: transitive description: name: permission_handler_android - sha256: f9fddd3b46109bd69ff3f9efa5006d2d309b7aec0f3c1c5637a60a2d5659e76e + sha256: "1acac6bae58144b442f11e66621c062aead9c99841093c38f5bcdcc24c1c3474" url: "https://pub.dev" source: hosted - version: "11.1.0" + version: "12.0.5" permission_handler_apple: dependency: transitive description: name: permission_handler_apple - sha256: "99e220bce3f8877c78e4ace901082fb29fa1b4ebde529ad0932d8d664b34f3f5" + sha256: e9ad66020b89ff1b63908f247c2c6f931c6e62699b756ef8b3c4569350cd8662 url: "https://pub.dev" source: hosted - version: "9.1.4" + version: "9.4.4" + permission_handler_html: + dependency: transitive + description: + name: permission_handler_html + sha256: "54bf176b90f6eddd4ece307e2c06cf977fb3973719c35a93b85cc7093eb6070d" + url: "https://pub.dev" + source: hosted + version: "0.1.1" permission_handler_platform_interface: dependency: transitive description: name: permission_handler_platform_interface - sha256: "6760eb5ef34589224771010805bea6054ad28453906936f843a8cc4d3a55c4a4" + sha256: "48d4fcf201a1dad93ee869ab0d4101d084f49136ec82a8a06ed9cfeacab9fd20" url: "https://pub.dev" source: hosted - version: "3.12.0" + version: "4.2.1" permission_handler_windows: dependency: transitive description: name: permission_handler_windows - sha256: cc074aace208760f1eee6aa4fae766b45d947df85bc831cde77009cdb4720098 + sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e" url: "https://pub.dev" source: hosted - version: "0.1.3" + version: "0.2.1" petitparser: dependency: transitive description: @@ -1701,10 +1709,10 @@ packages: dependency: "direct main" description: name: pointycastle - sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29" + sha256: "70fe966348fe08c34bf929582f1d8247d9d9408130723206472b4687227e4333" url: "https://pub.dev" source: hosted - version: "3.7.4" + version: "3.8.0" polylabel: dependency: transitive description: @@ -1781,10 +1789,10 @@ packages: dependency: "direct main" description: name: receive_sharing_intent - sha256: "8fdf5927934041264becf65199ef8057b8b176e879d95ffa0420cd2a6219c0fd" + sha256: fe02f858ac9f8d44d62e1964dadded000bb48dea424085ed280d542a61c4e8ba url: "https://pub.dev" source: hosted - version: "1.6.7" + version: "1.7.0" rxdart: dependency: transitive description: @@ -1861,18 +1869,18 @@ packages: dependency: "direct main" description: name: sentry - sha256: a460aa48568d47140dd0557410b624d344ffb8c05555107ac65035c1097cf1ad + sha256: fe99a06970b909a491b7f89d54c9b5119772e3a48a400308a6e129625b333f5b url: "https://pub.dev" source: hosted - version: "7.18.0" + version: "7.19.0" sentry_flutter: dependency: "direct main" description: name: sentry_flutter - sha256: "3d0d1d4e0e407d276ae8128d123263ccbc37e988bae906765efd6f37d544f4c6" + sha256: fc013d4a753447320f62989b1871fdc1f20c77befcc8be3e38774dd7402e7a62 url: "https://pub.dev" source: hosted - version: "7.18.0" + version: "7.19.0" share_plus: dependency: "direct main" description: From a67da8102d10eba71efda422b283bf1a9831cbc6 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Wed, 10 Apr 2024 18:12:42 +0530 Subject: [PATCH 08/84] fix breaking change --- mobile/lib/ui/tabs/home_widget.dart | 8 +++++--- mobile/pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/mobile/lib/ui/tabs/home_widget.dart b/mobile/lib/ui/tabs/home_widget.dart index 561b1f4ba1..802b40be89 100644 --- a/mobile/lib/ui/tabs/home_widget.dart +++ b/mobile/lib/ui/tabs/home_widget.dart @@ -284,7 +284,7 @@ class _HomeWidgetState extends State { void _initMediaShareSubscription() { // For sharing images coming from outside the app while the app is in the memory _intentDataStreamSubscription = - ReceiveSharingIntent.getMediaStream().listen( + ReceiveSharingIntent.instance.getMediaStream().listen( (List value) { setState(() { _shouldRenderCreateCollectionSheet = true; @@ -296,7 +296,9 @@ class _HomeWidgetState extends State { }, ); // For sharing images coming from outside the app while the app is closed - ReceiveSharingIntent.getInitialMedia().then((List value) { + ReceiveSharingIntent.instance + .getInitialMedia() + .then((List value) { if (mounted) { setState(() { _sharedFiles = value; @@ -380,7 +382,7 @@ class _HomeWidgetState extends State { //So to stop showing multiple CreateCollectionSheets, this flag //needs to be set to false the first time it is rendered. _shouldRenderCreateCollectionSheet = false; - ReceiveSharingIntent.reset(); + ReceiveSharingIntent.instance.reset(); Future.delayed(const Duration(milliseconds: 10), () { showCollectionActionSheet( context, diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index 33da8f0a55..56cb9331e2 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -137,7 +137,7 @@ dependencies: pointycastle: ^3.7.3 provider: ^6.0.0 quiver: ^3.0.1 - receive_sharing_intent: ^1.6.7 + receive_sharing_intent: ^1.7.0 scrollable_positioned_list: ^0.3.5 sentry: ^7.9.0 sentry_flutter: ^7.9.0 From 6607fce1445f1fcac6e4eeb25c9af915eca797a8 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Wed, 10 Apr 2024 18:13:27 +0530 Subject: [PATCH 09/84] fix not building on iOS --- mobile/ios/Podfile.lock | 163 +++++++++++--------- mobile/ios/Runner.xcodeproj/project.pbxproj | 23 +++ 2 files changed, 115 insertions(+), 71 deletions(-) diff --git a/mobile/ios/Podfile.lock b/mobile/ios/Podfile.lock index 13588f1a16..23819dbab4 100644 --- a/mobile/ios/Podfile.lock +++ b/mobile/ios/Podfile.lock @@ -1,8 +1,11 @@ PODS: - - background_fetch (1.2.1): + - background_fetch (1.3.2): - Flutter - battery_info (0.0.1): - Flutter + - bonsoir_darwin (3.0.0): + - Flutter + - FlutterMacOS - connectivity_plus (0.0.1): - Flutter - ReachabilitySwift @@ -10,38 +13,38 @@ PODS: - Flutter - file_saver (0.0.1): - Flutter - - Firebase/CoreOnly (10.18.0): - - FirebaseCore (= 10.18.0) - - Firebase/Messaging (10.18.0): + - Firebase/CoreOnly (10.22.0): + - FirebaseCore (= 10.22.0) + - Firebase/Messaging (10.22.0): - Firebase/CoreOnly - - FirebaseMessaging (~> 10.18.0) - - firebase_core (2.24.2): - - Firebase/CoreOnly (= 10.18.0) + - FirebaseMessaging (~> 10.22.0) + - firebase_core (2.27.0): + - Firebase/CoreOnly (= 10.22.0) - Flutter - - firebase_messaging (14.7.10): - - Firebase/Messaging (= 10.18.0) + - firebase_messaging (14.7.19): + - Firebase/Messaging (= 10.22.0) - firebase_core - Flutter - - FirebaseCore (10.18.0): + - FirebaseCore (10.22.0): - FirebaseCoreInternal (~> 10.0) - GoogleUtilities/Environment (~> 7.12) - GoogleUtilities/Logger (~> 7.12) - - FirebaseCoreInternal (10.21.0): + - FirebaseCoreInternal (10.24.0): - "GoogleUtilities/NSData+zlib (~> 7.8)" - - FirebaseInstallations (10.21.0): + - FirebaseInstallations (10.24.0): - FirebaseCore (~> 10.0) - GoogleUtilities/Environment (~> 7.8) - GoogleUtilities/UserDefaults (~> 7.8) - PromisesObjC (~> 2.1) - - FirebaseMessaging (10.18.0): + - FirebaseMessaging (10.22.0): - FirebaseCore (~> 10.0) - FirebaseInstallations (~> 10.0) - - GoogleDataTransport (~> 9.2) + - GoogleDataTransport (~> 9.3) - GoogleUtilities/AppDelegateSwizzler (~> 7.8) - GoogleUtilities/Environment (~> 7.8) - GoogleUtilities/Reachability (~> 7.8) - GoogleUtilities/UserDefaults (~> 7.8) - - nanopb (< 2.30910.0, >= 2.30908.0) + - nanopb (< 2.30911.0, >= 2.30908.0) - fk_user_agent (2.0.0): - Flutter - Flutter (1.0.0) @@ -70,27 +73,35 @@ PODS: - fluttertoast (0.0.2): - Flutter - Toast - - GoogleDataTransport (9.3.0): + - GoogleDataTransport (9.4.1): - GoogleUtilities/Environment (~> 7.7) - - nanopb (< 2.30910.0, >= 2.30908.0) + - nanopb (< 2.30911.0, >= 2.30908.0) - PromisesObjC (< 3.0, >= 1.2) - - GoogleUtilities/AppDelegateSwizzler (7.12.0): + - GoogleUtilities/AppDelegateSwizzler (7.13.0): - GoogleUtilities/Environment - GoogleUtilities/Logger - GoogleUtilities/Network - - GoogleUtilities/Environment (7.12.0): + - GoogleUtilities/Privacy + - GoogleUtilities/Environment (7.13.0): + - GoogleUtilities/Privacy - PromisesObjC (< 3.0, >= 1.2) - - GoogleUtilities/Logger (7.12.0): + - GoogleUtilities/Logger (7.13.0): - GoogleUtilities/Environment - - GoogleUtilities/Network (7.12.0): + - GoogleUtilities/Privacy + - GoogleUtilities/Network (7.13.0): - GoogleUtilities/Logger - "GoogleUtilities/NSData+zlib" + - GoogleUtilities/Privacy - GoogleUtilities/Reachability - - "GoogleUtilities/NSData+zlib (7.12.0)" - - GoogleUtilities/Reachability (7.12.0): + - "GoogleUtilities/NSData+zlib (7.13.0)": + - GoogleUtilities/Privacy + - GoogleUtilities/Privacy (7.13.0) + - GoogleUtilities/Reachability (7.13.0): - GoogleUtilities/Logger - - GoogleUtilities/UserDefaults (7.12.0): + - GoogleUtilities/Privacy + - GoogleUtilities/UserDefaults (7.13.0): - GoogleUtilities/Logger + - GoogleUtilities/Privacy - home_widget (0.0.1): - Flutter - image_editor_common (1.0.0): @@ -114,6 +125,8 @@ PODS: - libwebp/sharpyuv (1.3.2) - libwebp/webp (1.3.2): - libwebp/sharpyuv + - local_auth_darwin (0.0.1): + - Flutter - local_auth_ios (0.0.1): - Flutter - Mantle (2.2.0): @@ -131,11 +144,11 @@ PODS: - Flutter - move_to_background (0.0.1): - Flutter - - nanopb (2.30909.1): - - nanopb/decode (= 2.30909.1) - - nanopb/encode (= 2.30909.1) - - nanopb/decode (2.30909.1) - - nanopb/encode (2.30909.1) + - nanopb (2.30910.0): + - nanopb/decode (= 2.30910.0) + - nanopb/encode (= 2.30910.0) + - nanopb/decode (2.30910.0) + - nanopb/encode (2.30910.0) - onnxruntime (0.0.1): - Flutter - onnxruntime-objc (= 1.15.1) @@ -152,30 +165,30 @@ PODS: - path_provider_foundation (0.0.1): - Flutter - FlutterMacOS - - permission_handler_apple (9.1.1): + - permission_handler_apple (9.3.0): - Flutter - photo_manager (2.0.0): - Flutter - FlutterMacOS - - PromisesObjC (2.3.1) - - ReachabilitySwift (5.0.0) - - receive_sharing_intent (1.6.7): + - PromisesObjC (2.4.0) + - ReachabilitySwift (5.2.1) + - receive_sharing_intent (1.6.8): - Flutter - screen_brightness_ios (0.1.0): - Flutter - - SDWebImage (5.18.11): - - SDWebImage/Core (= 5.18.11) - - SDWebImage/Core (5.18.11) + - SDWebImage (5.19.1): + - SDWebImage/Core (= 5.19.1) + - SDWebImage/Core (5.19.1) - SDWebImageWebPCoder (0.14.5): - libwebp (~> 1.0) - SDWebImage/Core (~> 5.17) - - Sentry/HybridSDK (8.18.0): - - SentryPrivate (= 8.18.0) - - sentry_flutter (0.0.1): + - Sentry/HybridSDK (8.21.0): + - SentryPrivate (= 8.21.0) + - sentry_flutter (7.19.0): - Flutter - FlutterMacOS - - Sentry/HybridSDK (= 8.18.0) - - SentryPrivate (8.18.0) + - Sentry/HybridSDK (= 8.21.0) + - SentryPrivate (8.21.0) - share_plus (0.0.1): - Flutter - shared_preferences_foundation (0.0.1): @@ -195,11 +208,11 @@ PODS: - sqlite3/common - sqlite3_flutter_libs (0.0.1): - Flutter - - sqlite3 (~> 3.45.0) + - sqlite3 (~> 3.45.1) - sqlite3/fts5 - sqlite3/perf-threadsafe - sqlite3/rtree - - Toast (4.1.0) + - Toast (4.1.1) - uni_links (0.0.1): - Flutter - url_launcher_ios (0.0.1): @@ -218,6 +231,7 @@ PODS: DEPENDENCIES: - background_fetch (from `.symlinks/plugins/background_fetch/ios`) - battery_info (from `.symlinks/plugins/battery_info/ios`) + - bonsoir_darwin (from `.symlinks/plugins/bonsoir_darwin/darwin`) - connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`) - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`) - file_saver (from `.symlinks/plugins/file_saver/ios`) @@ -238,6 +252,7 @@ DEPENDENCIES: - in_app_purchase_storekit (from `.symlinks/plugins/in_app_purchase_storekit/darwin`) - integration_test (from `.symlinks/plugins/integration_test/ios`) - isar_flutter_libs (from `.symlinks/plugins/isar_flutter_libs/ios`) + - local_auth_darwin (from `.symlinks/plugins/local_auth_darwin/darwin`) - local_auth_ios (from `.symlinks/plugins/local_auth_ios/ios`) - media_extension (from `.symlinks/plugins/media_extension/ios`) - media_kit_libs_ios_video (from `.symlinks/plugins/media_kit_libs_ios_video/ios`) @@ -294,6 +309,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/background_fetch/ios" battery_info: :path: ".symlinks/plugins/battery_info/ios" + bonsoir_darwin: + :path: ".symlinks/plugins/bonsoir_darwin/darwin" connectivity_plus: :path: ".symlinks/plugins/connectivity_plus/ios" device_info_plus: @@ -334,6 +351,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/integration_test/ios" isar_flutter_libs: :path: ".symlinks/plugins/isar_flutter_libs/ios" + local_auth_darwin: + :path: ".symlinks/plugins/local_auth_darwin/darwin" local_auth_ios: :path: ".symlinks/plugins/local_auth_ios/ios" media_extension: @@ -388,20 +407,21 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/wakelock_plus/ios" SPEC CHECKSUMS: - background_fetch: 896944864b038d2837fc750d470e9841e1e6a363 + background_fetch: 2319bf7e18237b4b269430b7f14d177c0df09c5a battery_info: 09f5c9ee65394f2291c8c6227bedff345b8a730c - connectivity_plus: 53efb943fc2882c8512d84c45707bcabc4c36076 + bonsoir_darwin: 127bdc632fdc154ae2f277a4d5c86a6212bc75be + connectivity_plus: 07c49e96d7fc92bc9920617b83238c4d178b446a device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6 file_saver: 503e386464dbe118f630e17b4c2e1190fa0cf808 - Firebase: 414ad272f8d02dfbf12662a9d43f4bba9bec2a06 - firebase_core: 0af4a2b24f62071f9bf283691c0ee41556dcb3f5 - firebase_messaging: 90e8a6db84b6e1e876cebce4f30f01dc495e7014 - FirebaseCore: 2322423314d92f946219c8791674d2f3345b598f - FirebaseCoreInternal: 43c1788eaeee9d1b97caaa751af567ce11010d00 - FirebaseInstallations: 390ea1d10a4d02b20c965cbfd527ee9b3b412acb - FirebaseMessaging: 9bc34a98d2e0237e1b121915120d4d48ddcf301e + Firebase: 797fd7297b7e1be954432743a0b3f90038e45a71 + firebase_core: 100945864b4aedce3cfef0c62ab864858bf013cf + firebase_messaging: e65050bf9b187511d80ea3a4de7cf5573d2c7543 + FirebaseCore: 0326ec9b05fbed8f8716cddbf0e36894a13837f7 + FirebaseCoreInternal: bcb5acffd4ea05e12a783ecf835f2210ce3dc6af + FirebaseInstallations: 8f581fca6478a50705d2bd2abd66d306e0f5736e + FirebaseMessaging: 9f71037fd9db3376a4caa54e5a3949d1027b4b6e fk_user_agent: 1f47ec39291e8372b1d692b50084b0d54103c545 - Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 flutter_email_sender: 02d7443217d8c41483223627972bfdc09f74276b flutter_image_compress: 5a5e9aee05b6553048b8df1c3bc456d0afaac433 flutter_inappwebview: 3d32228f1304635e7c028b0d4252937730bbc6cf @@ -410,15 +430,16 @@ SPEC CHECKSUMS: flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be flutter_sodium: c84426b4de738514b5b66cfdeb8a06634e72fe0b fluttertoast: 31b00dabfa7fb7bacd9e7dbee580d7a2ff4bf265 - GoogleDataTransport: 57c22343ab29bc686febbf7cbb13bad167c2d8fe - GoogleUtilities: 0759d1a57ebb953965c2dfe0ba4c82e95ccc2e34 + GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a + GoogleUtilities: d053d902a8edaa9904e1bd00c37535385b8ed152 home_widget: 0434835a4c9a75704264feff6be17ea40e0f0d57 image_editor_common: d6f6644ae4a6de80481e89fe6d0a8c49e30b4b43 - in_app_purchase_storekit: 9e9931234f0adcf71ae323f8c83785b96030edf1 + in_app_purchase_storekit: 0e4b3c2e43ba1e1281f4f46dd71b0593ce529892 integration_test: 13825b8a9334a850581300559b8839134b124670 isar_flutter_libs: b69f437aeab9c521821c3f376198c4371fa21073 libwebp: 1786c9f4ff8a279e4dac1e8f385004d5fc253009 - local_auth_ios: 1ba1475238daa33a6ffa2a29242558437be435ac + local_auth_darwin: c7e464000a6a89e952235699e32b329457608d98 + local_auth_ios: 5046a18c018dd973247a0564496c8898dbb5adf9 Mantle: c5aa8794a29a022dfbbfc9799af95f477a69b62d media_extension: 6d30dc1431ebaa63f43c397c37917b1a0a597a4c media_kit_libs_ios_video: a5fe24bc7875ccd6378a0978c13185e1344651c1 @@ -426,7 +447,7 @@ SPEC CHECKSUMS: media_kit_video: 5da63f157170e5bf303bf85453b7ef6971218a2e motionphoto: d4a432b8c8f22fb3ad966258597c0103c9c5ff16 move_to_background: 39a5b79b26d577b0372cbe8a8c55e7aa9fcd3a2d - nanopb: d4d75c12cd1316f4a64e3c6963f879ecd4b5e0d5 + nanopb: 438bc412db1928dac798aa6fd75726007be04262 onnxruntime: e9346181d75b8dea8733bdae512a22c298962e00 onnxruntime-c: ebdcfd8650bcbd10121c125262f99dea681b92a3 onnxruntime-objc: ae7acec7a3d03eaf072d340afed7a35635c1c2a6 @@ -434,30 +455,30 @@ SPEC CHECKSUMS: OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85 path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c - permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6 + permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2 photo_manager: 4f6810b7dfc4feb03b461ac1a70dacf91fba7604 - PromisesObjC: c50d2056b5253dadbd6c2bea79b0674bd5a52fa4 - ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825 - receive_sharing_intent: 9ca20ae908f83c36ddaaaa8c9bd30ce4700495e8 + PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 + ReachabilitySwift: 5ae15e16814b5f9ef568963fb2c87aeb49158c66 + receive_sharing_intent: 6837b01768e567fe8562182397bf43d63d8c6437 screen_brightness_ios: 715ca807df953bf676d339f11464e438143ee625 - SDWebImage: a3ba0b8faac7228c3c8eadd1a55c9c9fe5e16457 + SDWebImage: 40b0b4053e36c660a764958bff99eed16610acbb SDWebImageWebPCoder: c94f09adbca681822edad9e532ac752db713eabf - Sentry: 8984a4ffb2b9bd2894d74fb36e6f5833865bc18e - sentry_flutter: c87a0556eeb6cbf7f9f924d30e878bdedf22d364 - SentryPrivate: 2f0c9ba4c3fc993f70eab6ca95673509561e0085 + Sentry: ebc12276bd17613a114ab359074096b6b3725203 + sentry_flutter: 88ebea3f595b0bc16acc5bedacafe6d60c12dcd5 + SentryPrivate: d651efb234cf385ec9a1cdd3eff94b5e78a0e0fe share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68 shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695 sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec sqlite3: 73b7fc691fdc43277614250e04d183740cb15078 - sqlite3_flutter_libs: aeb4d37509853dfa79d9b59386a2dac5dd079428 - Toast: ec33c32b8688982cecc6348adeae667c1b9938da + sqlite3_flutter_libs: af0e8fe9bce48abddd1ffdbbf839db0302d72d80 + Toast: 1f5ea13423a1e6674c4abdac5be53587ae481c4e uni_links: d97da20c7701486ba192624d99bffaaffcfc298a - url_launcher_ios: bbd758c6e7f9fd7b5b1d4cde34d2b95fcce5e812 - video_player_avfoundation: e9e6f9cae7d7a6d9b43519b0aab382bca60fcfd1 + url_launcher_ios: 6116280ddcfe98ab8820085d8d76ae7449447586 + video_player_avfoundation: 02011213dab73ae3687df27ce441fbbcc82b5579 video_thumbnail: c4e2a3c539e247d4de13cd545344fd2d26ffafd1 volume_controller: 531ddf792994285c9b17f9d8a7e4dcdd29b3eae9 wakelock_plus: 8b09852c8876491e4b6d179e17dfe2a0b5f60d47 PODFILE CHECKSUM: c1a8f198a245ed1f10e40b617efdb129b021b225 -COCOAPODS: 1.14.3 +COCOAPODS: 1.15.2 diff --git a/mobile/ios/Runner.xcodeproj/project.pbxproj b/mobile/ios/Runner.xcodeproj/project.pbxproj index 2ddddfd9f5..2478a5e885 100644 --- a/mobile/ios/Runner.xcodeproj/project.pbxproj +++ b/mobile/ios/Runner.xcodeproj/project.pbxproj @@ -174,6 +174,7 @@ 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, ABF2FD2FD606DC6DD54BD9AB /* [CP] Embed Pods Frameworks */, + F5BF2E85B889CF8483C26F35 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -292,6 +293,7 @@ "${BUILT_PRODUCTS_DIR}/Toast/Toast.framework", "${BUILT_PRODUCTS_DIR}/background_fetch/background_fetch.framework", "${BUILT_PRODUCTS_DIR}/battery_info/battery_info.framework", + "${BUILT_PRODUCTS_DIR}/bonsoir_darwin/bonsoir_darwin.framework", "${BUILT_PRODUCTS_DIR}/connectivity_plus/connectivity_plus.framework", "${BUILT_PRODUCTS_DIR}/device_info_plus/device_info_plus.framework", "${BUILT_PRODUCTS_DIR}/file_saver/file_saver.framework", @@ -310,6 +312,7 @@ "${BUILT_PRODUCTS_DIR}/integration_test/integration_test.framework", "${BUILT_PRODUCTS_DIR}/isar_flutter_libs/isar_flutter_libs.framework", "${BUILT_PRODUCTS_DIR}/libwebp/libwebp.framework", + "${BUILT_PRODUCTS_DIR}/local_auth_darwin/local_auth_darwin.framework", "${BUILT_PRODUCTS_DIR}/local_auth_ios/local_auth_ios.framework", "${BUILT_PRODUCTS_DIR}/media_extension/media_extension.framework", "${BUILT_PRODUCTS_DIR}/media_kit_libs_ios_video/media_kit_libs_ios_video.framework", @@ -374,6 +377,7 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Toast.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/background_fetch.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/battery_info.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/bonsoir_darwin.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/connectivity_plus.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/device_info_plus.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/file_saver.framework", @@ -392,6 +396,7 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/integration_test.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/isar_flutter_libs.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libwebp.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/local_auth_darwin.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/local_auth_ios.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/media_extension.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/media_kit_libs_ios_video.framework", @@ -464,6 +469,24 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; + F5BF2E85B889CF8483C26F35 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh", + "${PODS_CONFIGURATION_BUILD_DIR}/permission_handler_apple/permission_handler_apple_privacy.bundle", + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/permission_handler_apple_privacy.bundle", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ From 8137825693549bfb34e592b4706f4bddc5128ab3 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Fri, 12 Apr 2024 13:38:47 +0530 Subject: [PATCH 10/84] fix: explicitly add fill colour for textFields with filled flag set to true for it to remain the same as before using material 3 --- mobile/lib/ui/account/email_entry_page.dart | 13 ++++++++----- mobile/lib/ui/account/login_page.dart | 2 +- .../lib/ui/account/login_pwd_verification_page.dart | 1 + mobile/lib/ui/account/ott_verification_page.dart | 1 + mobile/lib/ui/account/password_entry_page.dart | 10 +++++++--- mobile/lib/ui/account/password_reentry_page.dart | 1 + mobile/lib/ui/account/recovery_page.dart | 1 + .../ui/account/request_pwd_verification_page.dart | 1 + mobile/lib/ui/account/verify_recovery_page.dart | 2 ++ mobile/lib/ui/viewer/search/search_widget.dart | 1 + 10 files changed, 24 insertions(+), 9 deletions(-) diff --git a/mobile/lib/ui/account/email_entry_page.dart b/mobile/lib/ui/account/email_entry_page.dart index 888542f160..143f593ef3 100644 --- a/mobile/lib/ui/account/email_entry_page.dart +++ b/mobile/lib/ui/account/email_entry_page.dart @@ -148,7 +148,9 @@ class _EmailEntryPageState extends State { style: Theme.of(context).textTheme.titleMedium, autofillHints: const [AutofillHints.email], decoration: InputDecoration( - fillColor: _emailIsValid ? _validFieldValueColor : null, + fillColor: _emailIsValid + ? _validFieldValueColor + : getEnteColorScheme(context).fillFaint, filled: true, hintText: S.of(context).email, contentPadding: const EdgeInsets.symmetric( @@ -195,8 +197,9 @@ class _EmailEntryPageState extends State { enableSuggestions: true, autofillHints: const [AutofillHints.newPassword], decoration: InputDecoration( - fillColor: - _passwordIsValid ? _validFieldValueColor : null, + fillColor: _passwordIsValid + ? _validFieldValueColor + : getEnteColorScheme(context).fillFaint, filled: true, hintText: S.of(context).password, contentPadding: const EdgeInsets.symmetric( @@ -265,7 +268,7 @@ class _EmailEntryPageState extends State { decoration: InputDecoration( fillColor: _passwordsMatch && _passwordIsValid ? _validFieldValueColor - : null, + : getEnteColorScheme(context).fillFaint, filled: true, hintText: S.of(context).confirmPassword, contentPadding: const EdgeInsets.symmetric( @@ -343,7 +346,7 @@ class _EmailEntryPageState extends State { child: TextFormField( style: Theme.of(context).textTheme.titleMedium, decoration: InputDecoration( - fillColor: null, + fillColor: getEnteColorScheme(context).fillFaint, filled: true, contentPadding: const EdgeInsets.symmetric( horizontal: 16, diff --git a/mobile/lib/ui/account/login_page.dart b/mobile/lib/ui/account/login_page.dart index 546a5f3b92..28b48a125f 100644 --- a/mobile/lib/ui/account/login_page.dart +++ b/mobile/lib/ui/account/login_page.dart @@ -237,7 +237,7 @@ class _LoginPageState extends State { if (_emailIsValid) { _emailInputFieldColor = const Color.fromRGBO(45, 194, 98, 0.2); } else { - _emailInputFieldColor = null; + _emailInputFieldColor = getEnteColorScheme(context).fillFaint; } } } diff --git a/mobile/lib/ui/account/login_pwd_verification_page.dart b/mobile/lib/ui/account/login_pwd_verification_page.dart index 884a5a4c7e..ac974c20da 100644 --- a/mobile/lib/ui/account/login_pwd_verification_page.dart +++ b/mobile/lib/ui/account/login_pwd_verification_page.dart @@ -251,6 +251,7 @@ class _LoginPasswordVerificationPageState borderSide: BorderSide.none, borderRadius: BorderRadius.circular(6), ), + fillColor: getEnteColorScheme(context).fillFaint, suffixIcon: _passwordInFocus ? IconButton( icon: Icon( diff --git a/mobile/lib/ui/account/ott_verification_page.dart b/mobile/lib/ui/account/ott_verification_page.dart index 9dee22e160..d03861055c 100644 --- a/mobile/lib/ui/account/ott_verification_page.dart +++ b/mobile/lib/ui/account/ott_verification_page.dart @@ -171,6 +171,7 @@ class _OTTVerificationPageState extends State { borderSide: BorderSide.none, borderRadius: BorderRadius.circular(6), ), + fillColor: getEnteColorScheme(context).fillFaint, ), controller: _verificationCodeController, autofocus: false, diff --git a/mobile/lib/ui/account/password_entry_page.dart b/mobile/lib/ui/account/password_entry_page.dart index a5099e333e..54b7af8507 100644 --- a/mobile/lib/ui/account/password_entry_page.dart +++ b/mobile/lib/ui/account/password_entry_page.dart @@ -12,6 +12,7 @@ import "package:photos/generated/l10n.dart"; import "package:photos/l10n/l10n.dart"; import "package:photos/models/key_gen_result.dart"; import 'package:photos/services/user_service.dart'; +import "package:photos/theme/ente_theme.dart"; import 'package:photos/ui/account/recovery_key_page.dart'; import 'package:photos/ui/common/dynamic_fab.dart'; import 'package:photos/ui/common/web_page.dart'; @@ -218,8 +219,9 @@ class _PasswordEntryPageState extends State { child: TextFormField( autofillHints: const [AutofillHints.newPassword], decoration: InputDecoration( - fillColor: - _isPasswordValid ? _validFieldValueColor : null, + fillColor: _isPasswordValid + ? _validFieldValueColor + : getEnteColorScheme(context).fillFaint, filled: true, hintText: S.of(context).password, contentPadding: const EdgeInsets.all(20), @@ -282,7 +284,9 @@ class _PasswordEntryPageState extends State { autofillHints: const [AutofillHints.newPassword], onEditingComplete: () => TextInput.finishAutofillContext(), decoration: InputDecoration( - fillColor: _passwordsMatch ? _validFieldValueColor : null, + fillColor: _passwordsMatch + ? _validFieldValueColor + : getEnteColorScheme(context).fillFaint, filled: true, hintText: S.of(context).confirmPassword, contentPadding: const EdgeInsets.symmetric( diff --git a/mobile/lib/ui/account/password_reentry_page.dart b/mobile/lib/ui/account/password_reentry_page.dart index cfbc30c10f..d3f6be5644 100644 --- a/mobile/lib/ui/account/password_reentry_page.dart +++ b/mobile/lib/ui/account/password_reentry_page.dart @@ -222,6 +222,7 @@ class _PasswordReentryPageState extends State { decoration: InputDecoration( hintText: S.of(context).enterYourPassword, filled: true, + fillColor: getEnteColorScheme(context).fillFaint, contentPadding: const EdgeInsets.all(20), border: UnderlineInputBorder( borderSide: BorderSide.none, diff --git a/mobile/lib/ui/account/recovery_page.dart b/mobile/lib/ui/account/recovery_page.dart index d5c651f92f..4b3d499955 100644 --- a/mobile/lib/ui/account/recovery_page.dart +++ b/mobile/lib/ui/account/recovery_page.dart @@ -103,6 +103,7 @@ class _RecoveryPageState extends State { child: TextFormField( decoration: InputDecoration( filled: true, + fillColor: getEnteColorScheme(context).fillFaint, hintText: S.of(context).enterYourRecoveryKey, contentPadding: const EdgeInsets.all(20), border: UnderlineInputBorder( diff --git a/mobile/lib/ui/account/request_pwd_verification_page.dart b/mobile/lib/ui/account/request_pwd_verification_page.dart index 9da169dea6..e29d568867 100644 --- a/mobile/lib/ui/account/request_pwd_verification_page.dart +++ b/mobile/lib/ui/account/request_pwd_verification_page.dart @@ -174,6 +174,7 @@ class _RequestPasswordVerificationPageState decoration: InputDecoration( hintText: context.l10n.enterYourPassword, filled: true, + fillColor: getEnteColorScheme(context).fillFaint, contentPadding: const EdgeInsets.all(20), border: UnderlineInputBorder( borderSide: BorderSide.none, diff --git a/mobile/lib/ui/account/verify_recovery_page.dart b/mobile/lib/ui/account/verify_recovery_page.dart index 063d5f4b15..f4acc47385 100644 --- a/mobile/lib/ui/account/verify_recovery_page.dart +++ b/mobile/lib/ui/account/verify_recovery_page.dart @@ -11,6 +11,7 @@ import "package:photos/generated/l10n.dart"; import 'package:photos/services/local_authentication_service.dart'; import 'package:photos/services/user_remote_flag_service.dart'; import 'package:photos/services/user_service.dart'; +import "package:photos/theme/ente_theme.dart"; import 'package:photos/ui/account/recovery_key_page.dart'; import 'package:photos/ui/common/gradient_button.dart'; import 'package:photos/ui/components/buttons/button_widget.dart'; @@ -162,6 +163,7 @@ class _VerifyRecoveryPageState extends State { TextFormField( decoration: InputDecoration( filled: true, + fillColor: getEnteColorScheme(context).fillFaint, hintText: S.of(context).enterYourRecoveryKey, contentPadding: const EdgeInsets.all(20), border: UnderlineInputBorder( diff --git a/mobile/lib/ui/viewer/search/search_widget.dart b/mobile/lib/ui/viewer/search/search_widget.dart index c624a78b32..2beaa1ec19 100644 --- a/mobile/lib/ui/viewer/search/search_widget.dart +++ b/mobile/lib/ui/viewer/search/search_widget.dart @@ -142,6 +142,7 @@ class SearchWidgetState extends State { //TODO: Extract string hintText: "Search", filled: true, + fillColor: getEnteColorScheme(context).fillFaint, border: const UnderlineInputBorder( borderSide: BorderSide.none, ), From 04e45b7908ce2cbe9d1830528f4e27c346cea91f Mon Sep 17 00:00:00 2001 From: ashilkn Date: Sat, 13 Apr 2024 12:41:08 +0530 Subject: [PATCH 11/84] fix: call updateEmail after initState to avoid runtime exception updateEmail uses getEnteColorScheme() which adds an inherited widget as dependency to the widget. Adding an inherited widget as dependency before init state is completed throws an exception --- mobile/lib/ui/account/login_page.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mobile/lib/ui/account/login_page.dart b/mobile/lib/ui/account/login_page.dart index 28b48a125f..7d79dc8567 100644 --- a/mobile/lib/ui/account/login_page.dart +++ b/mobile/lib/ui/account/login_page.dart @@ -29,18 +29,18 @@ class _LoginPageState extends State { final Logger _logger = Logger('_LoginPageState'); @override - void initState() { + void didChangeDependencies() { + super.didChangeDependencies(); if ((_config.getEmail() ?? '').isNotEmpty) { updateEmail(_config.getEmail()!); } else if (kDebugMode) { updateEmail(const String.fromEnvironment("email")); } - super.initState(); } @override Widget build(BuildContext context) { - final isKeypadOpen = MediaQuery.of(context).viewInsets.bottom > 100; + final isKeypadOpen = MediaQuery.viewInsetsOf(context).bottom > 100; FloatingActionButtonLocation? fabLocation() { if (isKeypadOpen) { From 372ced25024c48f3db08d532a52cbac892b4bee0 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Sat, 13 Apr 2024 16:48:36 +0530 Subject: [PATCH 12/84] [mob] fix colour of loading dialog --- mobile/lib/utils/dialog_util.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/mobile/lib/utils/dialog_util.dart b/mobile/lib/utils/dialog_util.dart index ae44256201..f9bd733ae5 100644 --- a/mobile/lib/utils/dialog_util.dart +++ b/mobile/lib/utils/dialog_util.dart @@ -291,7 +291,6 @@ ProgressDialog createProgressDialog( context, type: ProgressDialogType.normal, isDismissible: isDismissible, - barrierColor: Colors.black12, ); dialog.style( message: message, From 2c0148d66155ca15dc8e6a0c5130bd318af1e2ee Mon Sep 17 00:00:00 2001 From: ashilkn Date: Sat, 13 Apr 2024 17:11:04 +0530 Subject: [PATCH 13/84] [mob] fix UI of toggle widget on iOS --- mobile/ios/Podfile.lock | 2 +- .../ui/components/toggle_switch_widget.dart | 114 ++++++++++-------- mobile/pubspec.lock | 52 ++++---- 3 files changed, 89 insertions(+), 79 deletions(-) diff --git a/mobile/ios/Podfile.lock b/mobile/ios/Podfile.lock index 23819dbab4..a0a5005a5f 100644 --- a/mobile/ios/Podfile.lock +++ b/mobile/ios/Podfile.lock @@ -474,7 +474,7 @@ SPEC CHECKSUMS: Toast: 1f5ea13423a1e6674c4abdac5be53587ae481c4e uni_links: d97da20c7701486ba192624d99bffaaffcfc298a url_launcher_ios: 6116280ddcfe98ab8820085d8d76ae7449447586 - video_player_avfoundation: 02011213dab73ae3687df27ce441fbbcc82b5579 + video_player_avfoundation: 2b4384f3b157206b5e150a0083cdc0c905d260d3 video_thumbnail: c4e2a3c539e247d4de13cd545344fd2d26ffafd1 volume_controller: 531ddf792994285c9b17f9d8a7e4dcdd29b3eae9 wakelock_plus: 8b09852c8876491e4b6d179e17dfe2a0b5f60d47 diff --git a/mobile/lib/ui/components/toggle_switch_widget.dart b/mobile/lib/ui/components/toggle_switch_widget.dart index 9d1de15395..c00e635513 100644 --- a/mobile/lib/ui/components/toggle_switch_widget.dart +++ b/mobile/lib/ui/components/toggle_switch_widget.dart @@ -1,3 +1,6 @@ +import "dart:io"; + +import "package:flutter/cupertino.dart"; import 'package:flutter/material.dart'; import 'package:photos/ente_theme_data.dart'; import 'package:photos/models/execution_states.dart'; @@ -49,59 +52,23 @@ class _ToggleSwitchWidgetState extends State { height: 31, child: FittedBox( fit: BoxFit.contain, - child: Switch.adaptive( - inactiveTrackColor: Colors.transparent, - activeTrackColor: enteColorScheme.primary500, - activeColor: Colors.white, - inactiveThumbColor: enteColorScheme.primary500, - trackOutlineColor: MaterialStateColor.resolveWith( - (states) => enteColorScheme.primary500, - ), - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - value: toggleValue ?? false, - onChanged: (negationOfToggleValue) async { - setState(() { - toggleValue = negationOfToggleValue; - //start showing inProgress statu icons if toggle takes more than debounce time - _debouncer.run( - () => Future( - () { - setState(() { - executionState = ExecutionState.inProgress; - }); - }, + child: Platform.isAndroid + ? Switch( + inactiveTrackColor: Colors.transparent, + activeTrackColor: enteColorScheme.primary500, + activeColor: Colors.white, + inactiveThumbColor: enteColorScheme.primary500, + trackOutlineColor: MaterialStateColor.resolveWith( + (states) => enteColorScheme.primary500, ), - ); - }); - final Stopwatch stopwatch = Stopwatch()..start(); - await widget.onChanged.call().onError( - (error, stackTrace) => _debouncer.cancelDebounce(), - ); - //for toggle feedback on short unsuccessful onChanged - await _feedbackOnUnsuccessfulToggle(stopwatch); - //debouncer gets canceled if onChanged takes less than debounce time - _debouncer.cancelDebounce(); - - final newValue = widget.value.call(); - setState(() { - if (toggleValue == newValue) { - if (executionState == ExecutionState.inProgress) { - executionState = ExecutionState.successful; - Future.delayed(const Duration(seconds: 2), () { - if (mounted) { - setState(() { - executionState = ExecutionState.idle; - }); - } - }); - } - } else { - toggleValue = !toggleValue!; - executionState = ExecutionState.idle; - } - }); - }, - ), + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + value: toggleValue ?? false, + onChanged: onChanged, + ) + : CupertinoSwitch( + value: toggleValue ?? false, + onChanged: onChanged, + ), ), ), ], @@ -137,4 +104,47 @@ class _ToggleSwitchWidgetState extends State { ); } } + + Future onChanged(bool negationOfToggleValue) async { + setState(() { + toggleValue = negationOfToggleValue; + //start showing inProgress statu icons if toggle takes more than debounce time + _debouncer.run( + () => Future( + () { + setState(() { + executionState = ExecutionState.inProgress; + }); + }, + ), + ); + }); + final Stopwatch stopwatch = Stopwatch()..start(); + await widget.onChanged.call().onError( + (error, stackTrace) => _debouncer.cancelDebounce(), + ); + //for toggle feedback on short unsuccessful onChanged + await _feedbackOnUnsuccessfulToggle(stopwatch); + //debouncer gets canceled if onChanged takes less than debounce time + _debouncer.cancelDebounce(); + + final newValue = widget.value.call(); + setState(() { + if (toggleValue == newValue) { + if (executionState == ExecutionState.inProgress) { + executionState = ExecutionState.successful; + Future.delayed(const Duration(seconds: 2), () { + if (mounted) { + setState(() { + executionState = ExecutionState.idle; + }); + } + }); + } + } else { + toggleValue = !toggleValue!; + executionState = ExecutionState.idle; + } + }); + } } diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index ab3ca70204..3dcc023758 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -77,10 +77,10 @@ packages: dependency: transitive description: name: args - sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 + sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" url: "https://pub.dev" source: hosted - version: "2.4.2" + version: "2.5.0" async: dependency: transitive description: @@ -814,10 +814,10 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "592dc01a18961a51c24ae5d963b724b2b7fa4a95c100fe8eb6ca8a5a4732cadf" + sha256: "8cf40eebf5dec866a6d1956ad7b4f7016e6c0cc69847ab946833b7d43743809f" url: "https://pub.dev" source: hosted - version: "2.0.18" + version: "2.0.19" flutter_secure_storage: dependency: "direct main" description: @@ -920,10 +920,10 @@ packages: dependency: "direct dev" description: name: freezed - sha256: "91bce569d4805ea5bad6619a3e8690df8ad062a235165af4c0c5d928dda15eaf" + sha256: a434911f643466d78462625df76fd9eb13e57348ff43fe1f77bbe909522c67a1 url: "https://pub.dev" source: hosted - version: "2.5.1" + version: "2.5.2" freezed_annotation: dependency: "direct main" description: @@ -1061,10 +1061,10 @@ packages: dependency: transitive description: name: image_editor_ohos - sha256: "55c08871814efdd19b3927327b5913649dd1ea36e0a83aa77ab668dad3160dcc" + sha256: aee8fa1490fedbb98583dfaebb4162c295abeb0044e94f2eb2ad52ae419e6f6e url: "https://pub.dev" source: hosted - version: "0.0.6" + version: "0.0.7" image_editor_platform_interface: dependency: transitive description: @@ -1085,10 +1085,10 @@ packages: dependency: transitive description: name: in_app_purchase_android - sha256: "6863bf74335ccbd80829e8c3d16176f90794f0f8593a4505a7ab79d17334a0bf" + sha256: b9d4ecf70c51ab46222502c050b1535f6249caf9d768c4abd856ea16a18a882d url: "https://pub.dev" source: hosted - version: "0.3.3" + version: "0.3.3+1" in_app_purchase_platform_interface: dependency: transitive description: @@ -1549,18 +1549,18 @@ packages: dependency: "direct main" description: name: path_provider - sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b + sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161 url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.3" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: "51f0d2c554cfbc9d6a312ab35152fc77e2f0b758ce9f1a444a3a1e5b8f3c6b7f" + sha256: a248d8146ee5983446bf03ed5ea8f6533129a12b11f12057ad1b4a67a2b3b41d url: "https://pub.dev" source: hosted - version: "2.2.3" + version: "2.2.4" path_provider_foundation: dependency: transitive description: @@ -1933,18 +1933,18 @@ packages: dependency: "direct main" description: name: shared_preferences - sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02" + sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180 url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.2.3" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06" + sha256: "1ee8bf911094a1b592de7ab29add6f826a7331fb854273d55918693d5364a1f2" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.2" shared_preferences_foundation: dependency: transitive description: @@ -2330,18 +2330,18 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: "0ecc004c62fd3ed36a2ffcbe0dd9700aee63bd7532d0b642a488b1ec310f492e" + sha256: "6ce1e04375be4eed30548f10a315826fd933c1e493206eab82eed01f438c8d2e" url: "https://pub.dev" source: hosted - version: "6.2.5" + version: "6.2.6" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: d4ed0711849dd8e33eb2dd69c25db0d0d3fdc37e0a62e629fe32f57a22db2745 + sha256: "360a6ed2027f18b73c8d98e159dda67a61b7f2e0f6ec26e86c3ada33b0621775" url: "https://pub.dev" source: hosted - version: "6.3.0" + version: "6.3.1" url_launcher_ios: dependency: transitive description: @@ -2419,18 +2419,18 @@ packages: dependency: transitive description: name: video_player_android - sha256: "4dd9b8b86d70d65eecf3dcabfcdfbb9c9115d244d022654aba49a00336d540c2" + sha256: "821cff3446bbde255e8d03c12fe1f9810c69fee2c26c394545b13d824ba63c2e" url: "https://pub.dev" source: hosted - version: "2.4.12" + version: "2.4.13" video_player_avfoundation: dependency: transitive description: name: video_player_avfoundation - sha256: "309e3962795e761be010869bae65c0b0e45b5230c5cee1bec72197ca7db040ed" + sha256: "00c49b1d68071341397cf760b982c1e26ed9232464c8506ee08378a5cca5070d" url: "https://pub.dev" source: hosted - version: "2.5.6" + version: "2.5.7" video_player_platform_interface: dependency: transitive description: From 75dd7c3e48b677c9f9ef3b3119e5512bfcb5ea76 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Sat, 13 Apr 2024 17:15:13 +0530 Subject: [PATCH 14/84] [mob] make function private --- mobile/lib/ui/components/toggle_switch_widget.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mobile/lib/ui/components/toggle_switch_widget.dart b/mobile/lib/ui/components/toggle_switch_widget.dart index c00e635513..de6507c1f5 100644 --- a/mobile/lib/ui/components/toggle_switch_widget.dart +++ b/mobile/lib/ui/components/toggle_switch_widget.dart @@ -63,11 +63,11 @@ class _ToggleSwitchWidgetState extends State { ), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, value: toggleValue ?? false, - onChanged: onChanged, + onChanged: _onChanged, ) : CupertinoSwitch( value: toggleValue ?? false, - onChanged: onChanged, + onChanged: _onChanged, ), ), ), @@ -105,7 +105,7 @@ class _ToggleSwitchWidgetState extends State { } } - Future onChanged(bool negationOfToggleValue) async { + Future _onChanged(bool negationOfToggleValue) async { setState(() { toggleValue = negationOfToggleValue; //start showing inProgress statu icons if toggle takes more than debounce time From d864acafa3607f08753ec4c6156fc34875d02f32 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Fri, 12 Apr 2024 14:55:07 +0530 Subject: [PATCH 15/84] [mob] Upgrade to flutter 3.19.5 --- mobile/ios/Podfile.lock | 30 ++-- mobile/ios/Runner.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- mobile/lib/services/notification_service.dart | 7 +- mobile/pubspec.lock | 164 +++++++++--------- mobile/pubspec.yaml | 4 +- 6 files changed, 100 insertions(+), 109 deletions(-) diff --git a/mobile/ios/Podfile.lock b/mobile/ios/Podfile.lock index 82b2c256fc..46aa7d86b8 100644 --- a/mobile/ios/Podfile.lock +++ b/mobile/ios/Podfile.lock @@ -14,9 +14,9 @@ PODS: - FirebaseCore (= 10.18.0) - Firebase/Messaging (10.18.0): - Firebase/CoreOnly - - FirebaseMessaging (~> 10.18.0) - - firebase_core (2.24.2): - - Firebase/CoreOnly (= 10.18.0) + - FirebaseMessaging (~> 10.22.0) + - firebase_core (2.29.0): + - Firebase/CoreOnly (= 10.22.0) - Flutter - firebase_messaging (14.7.10): - Firebase/Messaging (= 10.18.0) @@ -388,19 +388,19 @@ SPEC CHECKSUMS: connectivity_plus: 53efb943fc2882c8512d84c45707bcabc4c36076 device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6 file_saver: 503e386464dbe118f630e17b4c2e1190fa0cf808 - Firebase: 414ad272f8d02dfbf12662a9d43f4bba9bec2a06 - firebase_core: 0af4a2b24f62071f9bf283691c0ee41556dcb3f5 - firebase_messaging: 90e8a6db84b6e1e876cebce4f30f01dc495e7014 - FirebaseCore: 2322423314d92f946219c8791674d2f3345b598f - FirebaseCoreInternal: 43c1788eaeee9d1b97caaa751af567ce11010d00 - FirebaseInstallations: 390ea1d10a4d02b20c965cbfd527ee9b3b412acb - FirebaseMessaging: 9bc34a98d2e0237e1b121915120d4d48ddcf301e + Firebase: 797fd7297b7e1be954432743a0b3f90038e45a71 + firebase_core: aaadbddb3cb2ee3792b9804f9dbb63e5f6f7b55c + firebase_messaging: e65050bf9b187511d80ea3a4de7cf5573d2c7543 + FirebaseCore: 0326ec9b05fbed8f8716cddbf0e36894a13837f7 + FirebaseCoreInternal: bcb5acffd4ea05e12a783ecf835f2210ce3dc6af + FirebaseInstallations: 8f581fca6478a50705d2bd2abd66d306e0f5736e + FirebaseMessaging: 9f71037fd9db3376a4caa54e5a3949d1027b4b6e fk_user_agent: 1f47ec39291e8372b1d692b50084b0d54103c545 Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 flutter_email_sender: 02d7443217d8c41483223627972bfdc09f74276b flutter_image_compress: 5a5e9aee05b6553048b8df1c3bc456d0afaac433 flutter_inappwebview: 3d32228f1304635e7c028b0d4252937730bbc6cf - flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743 + flutter_local_notifications: 4cde75091f6327eb8517fa068a0a5950212d2086 flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be flutter_sodium: c84426b4de738514b5b66cfdeb8a06634e72fe0b @@ -436,10 +436,10 @@ SPEC CHECKSUMS: screen_brightness_ios: 715ca807df953bf676d339f11464e438143ee625 SDWebImage: a3ba0b8faac7228c3c8eadd1a55c9c9fe5e16457 SDWebImageWebPCoder: c94f09adbca681822edad9e532ac752db713eabf - Sentry: 8984a4ffb2b9bd2894d74fb36e6f5833865bc18e - sentry_flutter: c87a0556eeb6cbf7f9f924d30e878bdedf22d364 - SentryPrivate: 2f0c9ba4c3fc993f70eab6ca95673509561e0085 - share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68 + Sentry: ebc12276bd17613a114ab359074096b6b3725203 + sentry_flutter: 88ebea3f595b0bc16acc5bedacafe6d60c12dcd5 + SentryPrivate: d651efb234cf385ec9a1cdd3eff94b5e78a0e0fe + share_plus: 8875f4f2500512ea181eef553c3e27dba5135aad shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695 sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec sqlite3: 73b7fc691fdc43277614250e04d183740cb15078 diff --git a/mobile/ios/Runner.xcodeproj/project.pbxproj b/mobile/ios/Runner.xcodeproj/project.pbxproj index 2ddddfd9f5..bb053d9994 100644 --- a/mobile/ios/Runner.xcodeproj/project.pbxproj +++ b/mobile/ios/Runner.xcodeproj/project.pbxproj @@ -191,7 +191,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 1520; - LastUpgradeCheck = 1430; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = "The Chromium Authors"; TargetAttributes = { 97C146ED1CF9000F007C117D = { diff --git a/mobile/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/mobile/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index a6b826db27..5e31d3d342 100644 --- a/mobile/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/mobile/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ init( void Function( NotificationResponse notificationResponse, - ) - onNotificationTapped, - SharedPreferences preferences, + ) onNotificationTapped, + SharedPreferences preferences, ) async { _preferences = preferences; const androidSettings = AndroidInitializationSettings('notification_icon'); @@ -72,7 +71,7 @@ class NotificationService { result = await _notificationsPlugin .resolvePlatformSpecificImplementation< AndroidFlutterLocalNotificationsPlugin>() - ?.requestPermission(); + ?.requestNotificationsPermission(); } if (result != null) { await _preferences.setBool(keyGrantedNotificationPermission, result); diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index e170a2bb3a..752d7a1738 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -13,10 +13,10 @@ packages: dependency: transitive description: name: _flutterfire_internals - sha256: "4eec93681221723a686ad580c2e7d960e1017cf1a4e0a263c2573c2c6b0bf5cd" + sha256: "0cb43f83f36ba8cb20502dee0c205e3f3aafb751732d724aeac3f2e044212cc2" url: "https://pub.dev" source: hosted - version: "1.3.25" + version: "1.3.29" adaptive_theme: dependency: "direct main" description: @@ -350,18 +350,18 @@ packages: dependency: transitive description: name: coverage - sha256: "595a29b55ce82d53398e1bcc2cba525d7bd7c59faeb2d2540e9d42c390cfeeeb" + sha256: "8acabb8306b57a409bf4c83522065672ee13179297a6bb0cb9ead73948df7c76" url: "https://pub.dev" source: hosted - version: "1.6.4" + version: "1.7.2" cross_file: dependency: "direct main" description: name: cross_file - sha256: fedaadfa3a6996f75211d835aaeb8fede285dae94262485698afd832371b9a5e + sha256: "55d7b444feb71301ef6b8838dbc1ae02e63dd48c8773f3810ff53bb1e2945b32" url: "https://pub.dev" source: hosted - version: "0.3.3+8" + version: "0.3.4+1" crypto: dependency: "direct main" description: @@ -526,10 +526,10 @@ packages: dependency: transitive description: name: extended_image_library - sha256: "9b55fc5ebc65fad984de66b8f177a1bef2a84d79203c9c213f75ff83c2c29edd" + sha256: c9caee8fe9b6547bd41c960c4f2d1ef8e34321804de6a1777f1d614a24247ad6 url: "https://pub.dev" source: hosted - version: "4.0.1" + version: "4.0.4" fade_indexed_stack: dependency: "direct main" description: @@ -574,10 +574,10 @@ packages: dependency: transitive description: name: file - sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" url: "https://pub.dev" source: hosted - version: "6.1.4" + version: "7.0.0" file_saver: dependency: "direct main" description: @@ -591,10 +591,10 @@ packages: dependency: "direct main" description: name: firebase_core - sha256: "53316975310c8af75a96e365f9fccb67d1c544ef0acdbf0d88bbe30eedd1c4f9" + sha256: a864d1b6afd25497a3b57b016886d1763df52baaa69758a46723164de8d187fe url: "https://pub.dev" source: hosted - version: "2.27.0" + version: "2.29.0" firebase_core_platform_interface: dependency: transitive description: @@ -607,10 +607,10 @@ packages: dependency: transitive description: name: firebase_core_web - sha256: c8e1d59385eee98de63c92f961d2a7062c5d9a65e7f45bdc7f1b0b205aab2492 + sha256: c8b02226e548f35aace298e2bb2e6c24e34e8a203d614e742bb1146e5a4ad3c8 url: "https://pub.dev" source: hosted - version: "2.11.5" + version: "2.15.0" firebase_messaging: dependency: "direct main" description: @@ -623,18 +623,18 @@ packages: dependency: transitive description: name: firebase_messaging_platform_interface - sha256: f7a9d74ff7fc588a924f6b2eaeaa148b0db521b13a9db55f6ad45864fa98c06e + sha256: "80b4ccf20066b0579ebc88d4678230a5f53ab282fe040e31671af745db1588f9" url: "https://pub.dev" source: hosted - version: "4.5.27" + version: "4.5.31" firebase_messaging_web: dependency: transitive description: name: firebase_messaging_web - sha256: fc21e771166860c55b103701c5ac7cdb2eec28897b97c42e6e5703cbedf9e02e + sha256: "9224aa4db1ce6f08d96a82978453d37e9980204a20e410a11d9b774b24c6841c" url: "https://pub.dev" source: hosted - version: "3.6.8" + version: "3.8.1" fixnum: dependency: transitive description: @@ -745,26 +745,26 @@ packages: dependency: "direct main" description: name: flutter_local_notifications - sha256: f222919a34545931e47b06000836b5101baeffb0e6eb5a4691d2d42851740dd9 + sha256: f9a05409385b77b06c18f200a41c7c2711ebf7415669350bb0f8474c07bd40d1 url: "https://pub.dev" source: hosted - version: "12.0.4" + version: "17.0.0" flutter_local_notifications_linux: dependency: transitive description: name: flutter_local_notifications_linux - sha256: "3c6d6db334f609a92be0c0915f40871ec56f5d2adf01e77ae364162c587c0ca8" + sha256: "33f741ef47b5f63cc7f78fe75eeeac7e19f171ff3c3df054d84c1e38bedb6a03" url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "4.0.0+1" flutter_local_notifications_platform_interface: dependency: transitive description: name: flutter_local_notifications_platform_interface - sha256: "5ec1feac5f7f7d9266759488bc5f76416152baba9aa1b26fe572246caa00d1ab" + sha256: "7cf643d6d5022f3baed0be777b0662cce5919c0a7b86e700299f22dc4ae660ef" url: "https://pub.dev" source: hosted - version: "6.0.0" + version: "7.0.0+1" flutter_localizations: dependency: "direct main" description: flutter @@ -1006,10 +1006,10 @@ packages: dependency: "direct main" description: name: http - sha256: a2bbf9d017fcced29139daa8ed2bba4ece450ab222871df93ca9eec6f80c34ba + sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.2.1" http_client_helper: dependency: transitive description: @@ -1183,6 +1183,30 @@ packages: url: "https://pub.dev" source: hosted version: "0.9.1" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + url: "https://pub.dev" + source: hosted + version: "10.0.0" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + url: "https://pub.dev" + source: hosted + version: "2.0.1" like_button: dependency: "direct main" description: @@ -1283,18 +1307,18 @@ packages: dependency: transitive description: name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb url: "https://pub.dev" source: hosted - version: "0.12.16" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.8.0" media_extension: dependency: "direct main" description: @@ -1379,10 +1403,10 @@ packages: dependency: transitive description: name: meta - sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.0" mgrs_dart: dependency: transitive description: @@ -1526,10 +1550,10 @@ packages: dependency: "direct main" description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.9.0" path_drawing: dependency: transitive description: @@ -1646,10 +1670,10 @@ packages: dependency: transitive description: name: platform - sha256: ae68c7bfcd7383af3629daafb32fb4e8681c7154428da4febcff06200585f102 + sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" url: "https://pub.dev" source: hosted - version: "3.1.2" + version: "3.1.4" plugin_platform_interface: dependency: transitive description: @@ -1686,10 +1710,10 @@ packages: dependency: transitive description: name: process - sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + sha256: "21e54fd2faf1b5bdd5102afd25012184a6793927648ea81eea80552ac9405b32" url: "https://pub.dev" source: hosted - version: "4.2.4" + version: "5.0.2" proj4dart: dependency: transitive description: @@ -1838,26 +1862,10 @@ packages: dependency: "direct main" description: name: share_plus - sha256: f582d5741930f3ad1bf0211d358eddc0508cc346e5b4b248bd1e569c995ebb7a + sha256: fb5319f3aab4c5dda5ebb92dca978179ba21f8c783ee4380910ef4c1c6824f51 url: "https://pub.dev" source: hosted - version: "4.5.3" - share_plus_linux: - dependency: transitive - description: - name: share_plus_linux - sha256: dc32bf9f1151b9864bb86a997c61a487967a08f2e0b4feaa9a10538712224da4 - url: "https://pub.dev" - source: hosted - version: "3.0.1" - share_plus_macos: - dependency: transitive - description: - name: share_plus_macos - sha256: "44daa946f2845045ecd7abb3569b61cd9a55ae9cc4cbec9895b2067b270697ae" - url: "https://pub.dev" - source: hosted - version: "3.0.1" + version: "8.0.3" share_plus_platform_interface: dependency: transitive description: @@ -1866,22 +1874,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.4.0" - share_plus_web: - dependency: transitive - description: - name: share_plus_web - sha256: eaef05fa8548b372253e772837dd1fbe4ce3aca30ea330765c945d7d4f7c9935 - url: "https://pub.dev" - source: hosted - version: "3.1.0" - share_plus_windows: - dependency: transitive - description: - name: share_plus_windows - sha256: "3a21515ae7d46988d42130cd53294849e280a5de6ace24bae6912a1bffd757d4" - url: "https://pub.dev" - source: hosted - version: "3.0.1" shared_preferences: dependency: "direct main" description: @@ -1926,10 +1918,10 @@ packages: dependency: transitive description: name: shared_preferences_web - sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21" + sha256: "9aee1089b36bd2aafe06582b7d7817fd317ef05fc30e6ba14bff247d0933042a" url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.3.0" shared_preferences_windows: dependency: transitive description: @@ -2323,10 +2315,10 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: fff0932192afeedf63cdd50ecbb1bc825d31aed259f02bb8dba0f3b729a5e88b + sha256: "3692a459204a33e04bc94f5fb91158faf4f2c8903281ddd82915adecdb1a901d" url: "https://pub.dev" source: hosted - version: "2.2.3" + version: "2.3.0" url_launcher_windows: dependency: transitive description: @@ -2412,10 +2404,10 @@ packages: dependency: transitive description: name: vm_service - sha256: c538be99af830f478718b51630ec1b6bee5e74e52c8a802d328d9e71d35d2583 + sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 url: "https://pub.dev" source: hosted - version: "11.10.0" + version: "13.0.0" volume_controller: dependency: transitive description: @@ -2460,10 +2452,10 @@ packages: dependency: transitive description: name: web - sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" url: "https://pub.dev" source: hosted - version: "0.3.0" + version: "0.5.1" web_socket_channel: dependency: transitive description: @@ -2476,10 +2468,10 @@ packages: dependency: transitive description: name: webdriver - sha256: "3c923e918918feeb90c4c9fdf1fe39220fa4c0e8e2c0fffaded174498ef86c49" + sha256: "003d7da9519e1e5f329422b36c4dcdf18d7d2978d1ba099ea4e45ba490ed845e" url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.0.3" webkit_inspection_protocol: dependency: transitive description: @@ -2532,10 +2524,10 @@ packages: dependency: transitive description: name: xdg_directories - sha256: bd512f03919aac5f1313eb8249f223bacf4927031bf60b02601f81f687689e86 + sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d url: "https://pub.dev" source: hosted - version: "0.2.0+3" + version: "1.0.4" xml: dependency: transitive description: @@ -2569,5 +2561,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.2.3 <4.0.0" - flutter: ">=3.16.6" + dart: ">=3.3.0 <4.0.0" + flutter: ">=3.19.0" diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index 8d39f93781..d2fd4c5919 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -78,7 +78,7 @@ dependencies: flutter_image_compress: ^1.1.0 flutter_inappwebview: ^5.8.0 flutter_launcher_icons: ^0.13.1 - flutter_local_notifications: ^12.0.4 + flutter_local_notifications: ^17.0.0 flutter_localizations: sdk: flutter flutter_map: ^5.0.0 @@ -143,7 +143,7 @@ dependencies: scrollable_positioned_list: ^0.3.5 sentry: ^7.9.0 sentry_flutter: ^7.9.0 - share_plus: ^4.0.10 + share_plus: ^8.0.3 shared_preferences: ^2.0.5 sqflite: ^2.3.0 sqflite_migration: ^0.3.0 From 952285468537e66363020f31e18b62fd9f825ce4 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Fri, 12 Apr 2024 15:53:22 +0530 Subject: [PATCH 16/84] Flutter gradle plugin changes --- mobile/android/app/build.gradle | 18 ++++++++++++------ mobile/android/build.gradle | 15 ++------------- mobile/android/settings.gradle | 30 ++++++++++++++++++++---------- 3 files changed, 34 insertions(+), 29 deletions(-) diff --git a/mobile/android/app/build.gradle b/mobile/android/app/build.gradle index a241cbe7e4..801efe6ebc 100644 --- a/mobile/android/app/build.gradle +++ b/mobile/android/app/build.gradle @@ -1,3 +1,8 @@ +plugins { + id "com.android.application" + id "kotlin-android" + id "dev.flutter.flutter-gradle-plugin" +} def localProperties = new Properties() def localPropertiesFile = rootProject.file('local.properties') if (localPropertiesFile.exists()) { @@ -6,10 +11,10 @@ if (localPropertiesFile.exists()) { } } -def flutterRoot = localProperties.getProperty('flutter.sdk') +/*def flutterRoot = localProperties.getProperty('flutter.sdk') if (flutterRoot == null) { throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") -} +}*/ def flutterVersionCode = localProperties.getProperty('flutter.versionCode') if (flutterVersionCode == null) { @@ -21,9 +26,10 @@ if (flutterVersionName == null) { flutterVersionName = '1.0' } -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" +//apply plugin: 'com.android.application' +//apply plugin: 'kotlin-android' +//apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + def keystoreProperties = new Properties() def keystorePropertiesFile = rootProject.file('key.properties') @@ -126,7 +132,7 @@ flutter { dependencies { implementation 'io.sentry:sentry-android:2.0.0' - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.21" implementation 'com.android.support:multidex:1.0.3' implementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava' testImplementation 'junit:junit:4.12' diff --git a/mobile/android/build.gradle b/mobile/android/build.gradle index ce75713c05..ad35549805 100644 --- a/mobile/android/build.gradle +++ b/mobile/android/build.gradle @@ -1,16 +1,5 @@ -buildscript { - ext.kotlin_version = '1.8.21' - repositories { - google() - jcenter() - } - - ext.appCompatVersion = '1.1.0' // for background_fetch - - dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath 'com.android.tools.build:gradle:7.1.2' // for background_fetch - } +ext { + appCompatVersion = '1.1.0' // for background_fetch } allprojects { diff --git a/mobile/android/settings.gradle b/mobile/android/settings.gradle index 5a2f14fb18..0fff0ecaf2 100644 --- a/mobile/android/settings.gradle +++ b/mobile/android/settings.gradle @@ -1,15 +1,25 @@ -include ':app' +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + }() -def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") -def plugins = new Properties() -def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') -if (pluginsFile.exists()) { - pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } + repositories { + google() + mavenCentral() + gradlePluginPortal() + } } -plugins.each { name, path -> - def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() - include ":$name" - project(":$name").projectDir = pluginDirectory +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "7.1.2" apply false + id "org.jetbrains.kotlin.android" version "1.8.21" apply false } + +include ":app" \ No newline at end of file From c183531e8bfa6347f50dc2caf5c88da921734366 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Fri, 12 Apr 2024 16:54:47 +0530 Subject: [PATCH 17/84] Switch to older version of share_plus --- mobile/lib/ui/account/recovery_key_page.dart | 5 +++-- mobile/pubspec.lock | 4 ++-- mobile/pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/mobile/lib/ui/account/recovery_key_page.dart b/mobile/lib/ui/account/recovery_key_page.dart index 6b4a116243..9ea3107096 100644 --- a/mobile/lib/ui/account/recovery_key_page.dart +++ b/mobile/lib/ui/account/recovery_key_page.dart @@ -11,7 +11,7 @@ import 'package:photos/ente_theme_data.dart'; import "package:photos/generated/l10n.dart"; import 'package:photos/ui/common/gradient_button.dart'; import 'package:photos/utils/toast_util.dart'; -import 'package:share_plus/share_plus.dart'; +import "package:share_plus/share_plus.dart"; import 'package:step_progress_indicator/step_progress_indicator.dart'; class RecoveryKeyPage extends StatefulWidget { @@ -248,7 +248,8 @@ class _RecoveryKeyPageState extends State { await _recoveryKeyFile.delete(); } _recoveryKeyFile.writeAsStringSync(recoveryKey); - await Share.shareFiles([_recoveryKeyFile.path]); + + await Share.shareXFiles([XFile(_recoveryKeyFile.path)]); Future.delayed(const Duration(milliseconds: 500), () { if (mounted) { setState(() { diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index 752d7a1738..970383016a 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -1862,10 +1862,10 @@ packages: dependency: "direct main" description: name: share_plus - sha256: fb5319f3aab4c5dda5ebb92dca978179ba21f8c783ee4380910ef4c1c6824f51 + sha256: "3ef39599b00059db0990ca2e30fca0a29d8b37aae924d60063f8e0184cf20900" url: "https://pub.dev" source: hosted - version: "8.0.3" + version: "7.2.2" share_plus_platform_interface: dependency: transitive description: diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index d2fd4c5919..dee9c67059 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -143,7 +143,7 @@ dependencies: scrollable_positioned_list: ^0.3.5 sentry: ^7.9.0 sentry_flutter: ^7.9.0 - share_plus: ^8.0.3 + share_plus: 7.2.2 shared_preferences: ^2.0.5 sqflite: ^2.3.0 sqflite_migration: ^0.3.0 From 2feee2cc5e27b54abea4aae1f98334bc64e53540 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Sat, 13 Apr 2024 17:58:41 +0530 Subject: [PATCH 18/84] [mob][photos] Bump flutter version in README and github workflow --- .github/workflows/mobile-lint.yml | 2 +- .github/workflows/mobile-release.yml | 2 +- mobile/README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/mobile-lint.yml b/.github/workflows/mobile-lint.yml index 48e38dc6ce..57b2ca4dbd 100644 --- a/.github/workflows/mobile-lint.yml +++ b/.github/workflows/mobile-lint.yml @@ -9,7 +9,7 @@ on: - ".github/workflows/mobile-lint.yml" env: - FLUTTER_VERSION: "3.13.4" + FLUTTER_VERSION: "3.19.5" jobs: lint: diff --git a/.github/workflows/mobile-release.yml b/.github/workflows/mobile-release.yml index 3ce4db8d2e..0f45df751d 100644 --- a/.github/workflows/mobile-release.yml +++ b/.github/workflows/mobile-release.yml @@ -9,7 +9,7 @@ on: - "photos-v*" env: - FLUTTER_VERSION: "3.13.4" + FLUTTER_VERSION: "3.19.5" jobs: build: diff --git a/mobile/README.md b/mobile/README.md index b9fcaff600..662e714033 100644 --- a/mobile/README.md +++ b/mobile/README.md @@ -46,7 +46,7 @@ You can alternatively install the build from PlayStore or F-Droid. ## 🧑‍💻 Building from source -1. [Install Flutter v3.16.9](https://flutter.dev/docs/get-started/install). +1. [Install Flutter v3.19.5](https://flutter.dev/docs/get-started/install). 2. Pull in all submodules with `git submodule update --init --recursive` From a3f102c183b2b161cd5394e51eb4294458b636ed Mon Sep 17 00:00:00 2001 From: ashilkn Date: Sat, 13 Apr 2024 18:07:01 +0530 Subject: [PATCH 19/84] [mob] Use custom toggle widget to remove UI issues after migrating to material 3 --- mobile/lib/models/typedefs.dart | 1 + .../lib/ui/sharing/manage_links_widget.dart | 29 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/mobile/lib/models/typedefs.dart b/mobile/lib/models/typedefs.dart index d358180da7..284d3a2445 100644 --- a/mobile/lib/models/typedefs.dart +++ b/mobile/lib/models/typedefs.dart @@ -18,3 +18,4 @@ typedef VoidCallbackParamSearchResutlsStream = void Function( typedef FutureVoidCallback = Future Function(); typedef FutureOrVoidCallback = FutureOr Function(); typedef FutureVoidCallbackParamStr = Future Function(String); +typedef FutureVoidCallbackParamBool = Future Function(bool); diff --git a/mobile/lib/ui/sharing/manage_links_widget.dart b/mobile/lib/ui/sharing/manage_links_widget.dart index 02878735e2..3478d1864f 100644 --- a/mobile/lib/ui/sharing/manage_links_widget.dart +++ b/mobile/lib/ui/sharing/manage_links_widget.dart @@ -15,6 +15,7 @@ import 'package:photos/ui/components/captioned_text_widget.dart'; import 'package:photos/ui/components/divider_widget.dart'; import 'package:photos/ui/components/menu_item_widget/menu_item_widget.dart'; 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/utils/crypto_util.dart'; @@ -78,14 +79,12 @@ class _ManageSharedLinkWidgetState extends State { ), alignCaptionedTextToLeft: true, menuItemColor: getEnteColorScheme(context).fillFaint, - trailingWidget: Switch.adaptive( - value: widget.collection!.publicURLs?.firstOrNull - ?.enableCollect ?? - false, - onChanged: (value) async { + trailingWidget: ToggleSwitchWidget( + value: () => isCollectEnabled, + onChanged: () async { await _updateUrlSettings( context, - {'enableCollect': value}, + {'enableCollect': !isCollectEnabled}, ); }, ), @@ -168,14 +167,14 @@ class _ManageSharedLinkWidgetState extends State { isBottomBorderRadiusRemoved: true, isTopBorderRadiusRemoved: true, menuItemColor: getEnteColorScheme(context).fillFaint, - trailingWidget: Switch.adaptive( - value: isDownloadEnabled, - onChanged: (value) async { + trailingWidget: ToggleSwitchWidget( + value: () => isDownloadEnabled, + onChanged: () async { await _updateUrlSettings( context, - {'enableDownload': value}, + {'enableDownload': !isDownloadEnabled}, ); - if (!value) { + if (!isDownloadEnabled) { // ignore: unawaited_futures showErrorDialog( context, @@ -198,10 +197,10 @@ class _ManageSharedLinkWidgetState extends State { alignCaptionedTextToLeft: true, isTopBorderRadiusRemoved: true, menuItemColor: getEnteColorScheme(context).fillFaint, - trailingWidget: Switch.adaptive( - value: isPasswordEnabled, - onChanged: (enablePassword) async { - if (enablePassword) { + trailingWidget: ToggleSwitchWidget( + value: () => isPasswordEnabled, + onChanged: () async { + if (!isPasswordEnabled) { // ignore: unawaited_futures showTextInputDialog( context, From 4c93033522e70013eec765f5643edb931325eed9 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Sat, 13 Apr 2024 18:08:57 +0530 Subject: [PATCH 20/84] [mob] Upgrade sqflite_async --- mobile/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index 060b93d844..fc669a783d 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -147,7 +147,7 @@ dependencies: sqflite_migration: ^0.3.0 sqlite3: ^2.1.0 sqlite3_flutter_libs: ^0.5.20 - sqlite_async: ^0.5.2 + sqlite_async: ^0.6.1 step_progress_indicator: ^1.0.2 styled_text: ^7.0.0 syncfusion_flutter_core: ^19.2.49 From 10cb54ddc11c8e131370a0bfa6e3d0c0c5efdcb3 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Sat, 13 Apr 2024 19:43:19 +0530 Subject: [PATCH 21/84] [mob] Use SegmentedButton instead of broken(UI) toggle in stripe subscription page --- .../ui/payment/stripe_subscription_page.dart | 46 +++++++++---------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/mobile/lib/ui/payment/stripe_subscription_page.dart b/mobile/lib/ui/payment/stripe_subscription_page.dart index 4a04d49d1a..0c63c71223 100644 --- a/mobile/lib/ui/payment/stripe_subscription_page.dart +++ b/mobile/lib/ui/payment/stripe_subscription_page.dart @@ -537,21 +537,6 @@ class _StripeSubscriptionPageState extends State { } Widget _showSubscriptionToggle() { - Widget planText(String title, bool reduceOpacity) { - return Padding( - padding: const EdgeInsets.only(left: 4, right: 4), - child: Text( - title, - style: TextStyle( - color: Theme.of(context) - .colorScheme - .onSurface - .withOpacity(reduceOpacity ? 0.5 : 1.0), - ), - ), - ); - } - return Container( padding: const EdgeInsets.only(left: 8, right: 8, top: 2, bottom: 2), margin: const EdgeInsets.only(bottom: 6), @@ -561,18 +546,29 @@ class _StripeSubscriptionPageState extends State { child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - planText(S.of(context).monthly, _showYearlyPlan), - Switch( - value: _showYearlyPlan, - activeColor: Colors.white, - inactiveThumbColor: Colors.white, - activeTrackColor: getEnteColorScheme(context).strokeMuted, - onChanged: (value) async { - _showYearlyPlan = value; - await _filterStripeForUI(); + SegmentedButton( + style: SegmentedButton.styleFrom( + selectedBackgroundColor: + getEnteColorScheme(context).fillMuted, + selectedForegroundColor: + getEnteColorScheme(context).textBase, + ), + segments: >[ + ButtonSegment( + label: Text(S.of(context).monthly), + value: false, + ), + ButtonSegment( + label: Text(S.of(context).yearly), + value: true, + ), + ], + selected: {_showYearlyPlan}, + onSelectionChanged: (p0) { + _showYearlyPlan = p0.first; + _filterStripeForUI(); }, ), - planText(S.of(context).yearly, !_showYearlyPlan), ], ), ), From d35fe3ff0043366e9c9622ccf826ea5fbce1b0fa Mon Sep 17 00:00:00 2001 From: ashilkn Date: Sat, 13 Apr 2024 19:44:22 +0530 Subject: [PATCH 22/84] [mob] Use SegmentedButton instead of broken(UI) toggle in app store subscription page --- .../ui/payment/store_subscription_page.dart | 46 +++++++++---------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/mobile/lib/ui/payment/store_subscription_page.dart b/mobile/lib/ui/payment/store_subscription_page.dart index 4bcdd4d5b6..c9f38d04e0 100644 --- a/mobile/lib/ui/payment/store_subscription_page.dart +++ b/mobile/lib/ui/payment/store_subscription_page.dart @@ -385,21 +385,6 @@ class _StoreSubscriptionPageState extends State { } Widget _showSubscriptionToggle() { - Widget planText(String title, bool reduceOpacity) { - return Padding( - padding: const EdgeInsets.only(left: 4, right: 4), - child: Text( - title, - style: TextStyle( - color: Theme.of(context) - .colorScheme - .onSurface - .withOpacity(reduceOpacity ? 0.5 : 1.0), - ), - ), - ); - } - return Container( padding: const EdgeInsets.only(left: 8, right: 8, top: 2, bottom: 2), margin: const EdgeInsets.only(bottom: 6), @@ -409,18 +394,29 @@ class _StoreSubscriptionPageState extends State { child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - planText(S.of(context).monthly, showYearlyPlan), - Switch( - value: showYearlyPlan, - activeColor: Colors.white, - inactiveThumbColor: Colors.white, - activeTrackColor: getEnteColorScheme(context).strokeMuted, - onChanged: (value) async { - showYearlyPlan = value; - await _filterStorePlansForUi(); + SegmentedButton( + style: SegmentedButton.styleFrom( + selectedBackgroundColor: + getEnteColorScheme(context).fillMuted, + selectedForegroundColor: + getEnteColorScheme(context).textBase, + ), + segments: >[ + ButtonSegment( + label: Text(S.of(context).monthly), + value: false, + ), + ButtonSegment( + label: Text(S.of(context).yearly), + value: true, + ), + ], + selected: {showYearlyPlan}, + onSelectionChanged: (p0) { + showYearlyPlan = p0.first; + _filterStorePlansForUi(); }, ), - planText(S.of(context).yearly, !showYearlyPlan), ], ), ), From 6c75b3547246babe4dede1a2d26d175ef5bd84b9 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Sat, 13 Apr 2024 19:45:06 +0530 Subject: [PATCH 23/84] [mob] pub upgrade --- auth/pubspec.lock | 76 ++++++++++++++++++++--------------------- mobile/ios/Podfile.lock | 2 +- mobile/pubspec.lock | 4 +-- 3 files changed, 41 insertions(+), 41 deletions(-) diff --git a/auth/pubspec.lock b/auth/pubspec.lock index 73b3075cb5..2d61b77c39 100644 --- a/auth/pubspec.lock +++ b/auth/pubspec.lock @@ -53,10 +53,10 @@ packages: dependency: transitive description: name: args - sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 + sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" url: "https://pub.dev" source: hosted - version: "2.4.2" + version: "2.5.0" async: dependency: transitive description: @@ -157,10 +157,10 @@ packages: dependency: transitive description: name: built_value - sha256: fedde275e0a6b798c3296963c5cd224e3e1b55d0e478d5b7e65e6b540f363a0e + sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb url: "https://pub.dev" source: hosted - version: "8.9.1" + version: "8.9.2" characters: dependency: transitive description: @@ -318,10 +318,10 @@ packages: dependency: "direct main" description: name: dio - sha256: "0978e9a3e45305a80a7210dbeaf79d6ee8bee33f70c8e542dc654c952070217f" + sha256: "639179e1cc0957779e10dd5b786ce180c477c4c0aca5aaba5d1700fa2e834801" url: "https://pub.dev" source: hosted - version: "5.4.2+1" + version: "5.4.3" dotted_border: dependency: "direct main" description: @@ -586,10 +586,10 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: b068ffc46f82a55844acfa4fdbb61fad72fa2aef0905548419d97f0f95c456da + sha256: "8cf40eebf5dec866a6d1956ad7b4f7016e6c0cc69847ab946833b7d43743809f" url: "https://pub.dev" source: hosted - version: "2.0.17" + version: "2.0.19" flutter_secure_storage: dependency: "direct main" description: @@ -1053,18 +1053,18 @@ packages: dependency: "direct main" description: name: path_provider - sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b + sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161 url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.3" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668" + sha256: a248d8146ee5983446bf03ed5ea8f6533129a12b11f12057ad1b4a67a2b3b41d url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.2.4" path_provider_foundation: dependency: transitive description: @@ -1133,10 +1133,10 @@ packages: dependency: "direct main" description: name: pointycastle - sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29" + sha256: "70fe966348fe08c34bf929582f1d8247d9d9408130723206472b4687227e4333" url: "https://pub.dev" source: hosted - version: "3.7.4" + version: "3.8.0" pool: dependency: transitive description: @@ -1221,18 +1221,18 @@ packages: dependency: "direct main" description: name: sentry - sha256: a460aa48568d47140dd0557410b624d344ffb8c05555107ac65035c1097cf1ad + sha256: fe99a06970b909a491b7f89d54c9b5119772e3a48a400308a6e129625b333f5b url: "https://pub.dev" source: hosted - version: "7.18.0" + version: "7.19.0" sentry_flutter: dependency: "direct main" description: name: sentry_flutter - sha256: "3d0d1d4e0e407d276ae8128d123263ccbc37e988bae906765efd6f37d544f4c6" + sha256: fc013d4a753447320f62989b1871fdc1f20c77befcc8be3e38774dd7402e7a62 url: "https://pub.dev" source: hosted - version: "7.18.0" + version: "7.19.0" share_plus: dependency: "direct main" description: @@ -1253,18 +1253,18 @@ packages: dependency: "direct main" description: name: shared_preferences - sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02" + sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180 url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.2.3" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06" + sha256: "1ee8bf911094a1b592de7ab29add6f826a7331fb854273d55918693d5364a1f2" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.2" shared_preferences_foundation: dependency: transitive description: @@ -1387,10 +1387,10 @@ packages: description: path: sqflite ref: HEAD - resolved-ref: "075b3e2f81e691a19a500e7ff6db2953de7f83a9" + resolved-ref: f281785e12e8b1abf2f9d41a587fc83d810724cf url: "https://github.com/tekartik/sqflite" source: git - version: "2.3.2" + version: "2.3.3" sqflite_common: dependency: transitive description: @@ -1411,10 +1411,10 @@ packages: dependency: "direct main" description: name: sqlite3 - sha256: "072128763f1547e3e9b4735ce846bfd226d68019ccda54db4cd427b12dfdedc9" + sha256: "1abbeb84bf2b1a10e5e1138c913123c8aa9d83cd64e5f9a0dd847b3c83063202" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.2" sqlite3_flutter_libs: dependency: "direct main" description: @@ -1515,10 +1515,10 @@ packages: dependency: "direct main" description: name: tray_manager - sha256: "4ab709d70a4374af172f8c39e018db33a4271265549c6fc9d269a65e5f4b0225" + sha256: e0ac9a88b2700f366b8629b97e8663b6ef450a2f169560a685dc167bfe9c9c29 url: "https://pub.dev" source: hosted - version: "0.2.1" + version: "0.2.2" tuple: dependency: "direct main" description: @@ -1547,18 +1547,18 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: "0ecc004c62fd3ed36a2ffcbe0dd9700aee63bd7532d0b642a488b1ec310f492e" + sha256: "6ce1e04375be4eed30548f10a315826fd933c1e493206eab82eed01f438c8d2e" url: "https://pub.dev" source: hosted - version: "6.2.5" + version: "6.2.6" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: d4ed0711849dd8e33eb2dd69c25db0d0d3fdc37e0a62e629fe32f57a22db2745 + sha256: "360a6ed2027f18b73c8d98e159dda67a61b7f2e0f6ec26e86c3ada33b0621775" url: "https://pub.dev" source: hosted - version: "6.3.0" + version: "6.3.1" url_launcher_ios: dependency: transitive description: @@ -1611,10 +1611,10 @@ packages: dependency: "direct main" description: name: uuid - sha256: cd210a09f7c18cbe5a02511718e0334de6559871052c90a90c0cca46a4aa81c8 + sha256: "814e9e88f21a176ae1359149021870e87f7cddaf633ab678a5d2b0bff7fd1ba8" url: "https://pub.dev" source: hosted - version: "4.3.3" + version: "4.4.0" vector_graphics: dependency: transitive description: @@ -1675,18 +1675,18 @@ packages: dependency: transitive description: name: web_socket_channel - sha256: "1d8e795e2a8b3730c41b8a98a2dff2e0fb57ae6f0764a1c46ec5915387d257b2" + sha256: "58c6666b342a38816b2e7e50ed0f1e261959630becd4c879c4f26bfa14aa5a42" url: "https://pub.dev" source: hosted - version: "2.4.4" + version: "2.4.5" win32: dependency: "direct main" description: name: win32 - sha256: "8cb58b45c47dcb42ab3651533626161d6b67a2921917d8d429791f76972b3480" + sha256: "0a989dc7ca2bb51eac91e8fd00851297cfffd641aa7538b165c62637ca0eaa4a" url: "https://pub.dev" source: hosted - version: "5.3.0" + version: "5.4.0" win32_registry: dependency: transitive description: diff --git a/mobile/ios/Podfile.lock b/mobile/ios/Podfile.lock index f8d2c3ad70..09f9ded3cb 100644 --- a/mobile/ios/Podfile.lock +++ b/mobile/ios/Podfile.lock @@ -481,4 +481,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: c1a8f198a245ed1f10e40b617efdb129b021b225 -COCOAPODS: 1.14.3 +COCOAPODS: 1.15.2 diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index 7669268598..f5a73696b3 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -2106,10 +2106,10 @@ packages: dependency: "direct main" description: name: sqlite_async - sha256: b252fd3a53766460b2f240e082517d3bc1cce7682a1550817f0f799d4a7a4087 + sha256: "139c8f1085132d0941b925efacb4fa0fed9ee40d624739cc26a051dbc36bf727" url: "https://pub.dev" source: hosted - version: "0.5.2" + version: "0.6.1" stack_trace: dependency: transitive description: From 81c47bc7689747a93244e4e68eab0dc96c2ec720 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Sat, 13 Apr 2024 20:01:28 +0530 Subject: [PATCH 24/84] [mob] UI changes to segmented button in stripe and store pages --- .../ui/payment/store_subscription_page.dart | 63 +++++++++++-------- .../ui/payment/stripe_subscription_page.dart | 63 +++++++++++-------- 2 files changed, 74 insertions(+), 52 deletions(-) diff --git a/mobile/lib/ui/payment/store_subscription_page.dart b/mobile/lib/ui/payment/store_subscription_page.dart index c9f38d04e0..3925bf0177 100644 --- a/mobile/lib/ui/payment/store_subscription_page.dart +++ b/mobile/lib/ui/payment/store_subscription_page.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'dart:io'; +import "package:flutter/cupertino.dart"; import "package:flutter/foundation.dart"; import 'package:flutter/material.dart'; import 'package:in_app_purchase/in_app_purchase.dart'; @@ -391,33 +392,43 @@ class _StoreSubscriptionPageState extends State { child: Column( children: [ RepaintBoundary( - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SegmentedButton( - style: SegmentedButton.styleFrom( - selectedBackgroundColor: - getEnteColorScheme(context).fillMuted, - selectedForegroundColor: - getEnteColorScheme(context).textBase, + child: SizedBox( + width: 250, + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: SegmentedButton( + style: SegmentedButton.styleFrom( + selectedBackgroundColor: + getEnteColorScheme(context).fillMuted, + selectedForegroundColor: + getEnteColorScheme(context).textBase, + side: BorderSide( + color: getEnteColorScheme(context).strokeMuted, + width: 1, + ), + ), + segments: >[ + ButtonSegment( + label: Text(S.of(context).monthly), + value: false, + ), + ButtonSegment( + label: Text(S.of(context).yearly), + value: true, + ), + ], + selected: {showYearlyPlan}, + onSelectionChanged: (p0) { + showYearlyPlan = p0.first; + _filterStorePlansForUi(); + }, + ), ), - segments: >[ - ButtonSegment( - label: Text(S.of(context).monthly), - value: false, - ), - ButtonSegment( - label: Text(S.of(context).yearly), - value: true, - ), - ], - selected: {showYearlyPlan}, - onSelectionChanged: (p0) { - showYearlyPlan = p0.first; - _filterStorePlansForUi(); - }, - ), - ], + ], + ), ), ), _isFreePlanUser() && !UpdateService.instance.isPlayStoreFlavor() diff --git a/mobile/lib/ui/payment/stripe_subscription_page.dart b/mobile/lib/ui/payment/stripe_subscription_page.dart index 0c63c71223..31694f174b 100644 --- a/mobile/lib/ui/payment/stripe_subscription_page.dart +++ b/mobile/lib/ui/payment/stripe_subscription_page.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import "package:flutter/cupertino.dart"; import "package:flutter/foundation.dart"; import 'package:flutter/material.dart'; import "package:logging/logging.dart"; @@ -543,33 +544,43 @@ class _StripeSubscriptionPageState extends State { child: Column( children: [ RepaintBoundary( - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SegmentedButton( - style: SegmentedButton.styleFrom( - selectedBackgroundColor: - getEnteColorScheme(context).fillMuted, - selectedForegroundColor: - getEnteColorScheme(context).textBase, + child: SizedBox( + width: 250, + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: SegmentedButton( + style: SegmentedButton.styleFrom( + selectedBackgroundColor: + getEnteColorScheme(context).fillMuted, + selectedForegroundColor: + getEnteColorScheme(context).textBase, + side: BorderSide( + color: getEnteColorScheme(context).strokeMuted, + width: 1, + ), + ), + segments: >[ + ButtonSegment( + label: Text(S.of(context).monthly), + value: false, + ), + ButtonSegment( + label: Text(S.of(context).yearly), + value: true, + ), + ], + selected: {_showYearlyPlan}, + onSelectionChanged: (p0) { + _showYearlyPlan = p0.first; + _filterStripeForUI(); + }, + ), ), - segments: >[ - ButtonSegment( - label: Text(S.of(context).monthly), - value: false, - ), - ButtonSegment( - label: Text(S.of(context).yearly), - value: true, - ), - ], - selected: {_showYearlyPlan}, - onSelectionChanged: (p0) { - _showYearlyPlan = p0.first; - _filterStripeForUI(); - }, - ), - ], + ], + ), ), ), _isFreePlanUser() && !UpdateService.instance.isPlayStoreFlavor() From c3de396d21d0c8d93c2852b9ee8fb3c9bfa63a8b Mon Sep 17 00:00:00 2001 From: ashilkn Date: Sat, 13 Apr 2024 20:06:32 +0530 Subject: [PATCH 25/84] [mob] bump up version to v0.8.80 --- mobile/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index dbf452164f..e35907251d 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -12,7 +12,7 @@ description: ente photos application # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 0.8.79+599 +version: 0.8.80+600 publish_to: none environment: From 45ab6d92b56334bf8e1904625baad997bee1fa4b Mon Sep 17 00:00:00 2001 From: Prateek Sunal Date: Sat, 13 Apr 2024 20:22:30 +0530 Subject: [PATCH 26/84] fix: also route to photo on click of widget --- mobile/lib/app.dart | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/mobile/lib/app.dart b/mobile/lib/app.dart index d4b8525404..3ab84a5d03 100644 --- a/mobile/lib/app.dart +++ b/mobile/lib/app.dart @@ -10,6 +10,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:home_widget/home_widget.dart' as hw; import 'package:logging/logging.dart'; import 'package:media_extension/media_extension_action_types.dart'; +import "package:photos/db/files_db.dart"; import 'package:photos/ente_theme_data.dart'; import "package:photos/generated/l10n.dart"; import "package:photos/l10n/l10n.dart"; @@ -22,6 +23,7 @@ import "package:photos/services/machine_learning/machine_learning_controller.dar import 'package:photos/services/sync_service.dart'; import 'package:photos/ui/tabs/home_widget.dart'; import "package:photos/ui/viewer/actions/file_viewer.dart"; +import "package:photos/ui/viewer/file/detail_page.dart"; import "package:photos/ui/viewer/gallery/collection_page.dart"; import "package:photos/utils/intent_util.dart"; import "package:photos/utils/navigation_util.dart"; @@ -90,15 +92,37 @@ class _EnteAppState extends State with WidgetsBindingObserver { final thumbnail = await CollectionsService.instance.getCover(collection); unawaited( - routeToPage( - context, - CollectionPage( - CollectionWithThumbnail( - collection, - thumbnail, + () async { + await routeToPage( + context, + CollectionPage( + CollectionWithThumbnail( + collection, + thumbnail, + ), ), - ), - ), + ); + + final previousGeneratedId = + await hw.HomeWidget.getWidgetData("home_widget_last_img"); + if (previousGeneratedId == null) return; + + final res = await FilesDB.instance.getFile( + previousGeneratedId, + ); + + if (res == null) return; + + final page = DetailPage( + DetailPageConfiguration( + List.unmodifiable([res]), + null, + 0, + "collection", + ), + ); + await routeToPage(context, page, forceCustomPageRoute: true); + }(), ); } From f04e45a461163b92cce7c0ceb87da8c0c5d20c31 Mon Sep 17 00:00:00 2001 From: Prateek Sunal Date: Sat, 13 Apr 2024 21:00:21 +0530 Subject: [PATCH 27/84] fix: logic of await/async --- mobile/lib/app.dart | 55 +++++++++++----------- mobile/lib/generated/intl/messages_zh.dart | 2 +- 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/mobile/lib/app.dart b/mobile/lib/app.dart index 3ab84a5d03..9d35d2a60c 100644 --- a/mobile/lib/app.dart +++ b/mobile/lib/app.dart @@ -91,39 +91,38 @@ class _EnteAppState extends State with WidgetsBindingObserver { unawaited(HomeWidgetService.instance.initHomeWidget()); final thumbnail = await CollectionsService.instance.getCover(collection); - unawaited( - () async { - await routeToPage( - context, - CollectionPage( - CollectionWithThumbnail( - collection, - thumbnail, - ), - ), - ); - final previousGeneratedId = - await hw.HomeWidget.getWidgetData("home_widget_last_img"); - if (previousGeneratedId == null) return; + final previousGeneratedId = + await hw.HomeWidget.getWidgetData("home_widget_last_img"); + final res = previousGeneratedId != null + ? await FilesDB.instance.getFile( + previousGeneratedId, + ) + : null; - final res = await FilesDB.instance.getFile( - previousGeneratedId, - ); + routeToPage( + context, + CollectionPage( + CollectionWithThumbnail( + collection, + thumbnail, + ), + ), + ).ignore(); - if (res == null) return; + if (previousGeneratedId == null) return; - final page = DetailPage( - DetailPageConfiguration( - List.unmodifiable([res]), - null, - 0, - "collection", - ), - ); - await routeToPage(context, page, forceCustomPageRoute: true); - }(), + if (res == null) return; + + final page = DetailPage( + DetailPageConfiguration( + List.unmodifiable([res]), + null, + 0, + "collection", + ), ); + routeToPage(context, page, forceCustomPageRoute: true).ignore(); } setLocale(Locale newLocale) { diff --git a/mobile/lib/generated/intl/messages_zh.dart b/mobile/lib/generated/intl/messages_zh.dart index 65e2af71f4..73d2ae0f5e 100644 --- a/mobile/lib/generated/intl/messages_zh.dart +++ b/mobile/lib/generated/intl/messages_zh.dart @@ -1026,7 +1026,7 @@ class MessageLookup extends MessageLookupByLibrary { "selectedFilesAreNotOnEnte": MessageLookupByLibrary.simpleMessage("所选文件不在 Ente 上"), "selectedFoldersWillBeEncryptedAndBackedUp": - MessageLookupByLibrary.simpleMessage("所选文件夹将被加密和备份"), + MessageLookupByLibrary.simpleMessage("所选文件夹将被加密并备份"), "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage("所选项目将从所有相册中删除并移动到回收站。"), "selectedPhotos": m46, From 5da8ee7e27796073daf9f071ca3b8fea36280d13 Mon Sep 17 00:00:00 2001 From: Prateek Sunal Date: Sun, 14 Apr 2024 14:35:10 +0530 Subject: [PATCH 28/84] fix: segregate logic for launch from widget --- mobile/lib/app.dart | 61 ++------------------ mobile/lib/services/home_widget_service.dart | 50 ++++++++++++++++ 2 files changed, 54 insertions(+), 57 deletions(-) diff --git a/mobile/lib/app.dart b/mobile/lib/app.dart index 9d35d2a60c..bc406d7c33 100644 --- a/mobile/lib/app.dart +++ b/mobile/lib/app.dart @@ -10,23 +10,16 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:home_widget/home_widget.dart' as hw; import 'package:logging/logging.dart'; import 'package:media_extension/media_extension_action_types.dart'; -import "package:photos/db/files_db.dart"; import 'package:photos/ente_theme_data.dart'; import "package:photos/generated/l10n.dart"; import "package:photos/l10n/l10n.dart"; -import "package:photos/models/collection/collection_items.dart"; import 'package:photos/services/app_lifecycle_service.dart'; -import "package:photos/services/collections_service.dart"; -import "package:photos/services/favorites_service.dart"; import "package:photos/services/home_widget_service.dart"; import "package:photos/services/machine_learning/machine_learning_controller.dart"; import 'package:photos/services/sync_service.dart'; import 'package:photos/ui/tabs/home_widget.dart'; import "package:photos/ui/viewer/actions/file_viewer.dart"; -import "package:photos/ui/viewer/file/detail_page.dart"; -import "package:photos/ui/viewer/gallery/collection_page.dart"; import "package:photos/utils/intent_util.dart"; -import "package:photos/utils/navigation_util.dart"; class EnteApp extends StatefulWidget { final Future Function(String) runBackgroundTask; @@ -68,61 +61,15 @@ class _EnteAppState extends State with WidgetsBindingObserver { void didChangeDependencies() { super.didChangeDependencies(); _checkForWidgetLaunch(); - hw.HomeWidget.widgetClicked.listen(_launchedFromWidget); } void _checkForWidgetLaunch() { - hw.HomeWidget.initiallyLaunchedFromHomeWidget().then(_launchedFromWidget); - } - - Future _launchedFromWidget(Uri? uri) async { - if (uri == null) return; - final collectionID = - await FavoritesService.instance.getFavoriteCollectionID(); - if (collectionID == null) { - return; - } - final collection = CollectionsService.instance.getCollectionByID( - collectionID, + hw.HomeWidget.initiallyLaunchedFromHomeWidget().then( + (uri) => HomeWidgetService.instance.onLaunchFromWidget(uri, context), ); - if (collection == null) { - return; - } - unawaited(HomeWidgetService.instance.initHomeWidget()); - - final thumbnail = await CollectionsService.instance.getCover(collection); - - final previousGeneratedId = - await hw.HomeWidget.getWidgetData("home_widget_last_img"); - final res = previousGeneratedId != null - ? await FilesDB.instance.getFile( - previousGeneratedId, - ) - : null; - - routeToPage( - context, - CollectionPage( - CollectionWithThumbnail( - collection, - thumbnail, - ), - ), - ).ignore(); - - if (previousGeneratedId == null) return; - - if (res == null) return; - - final page = DetailPage( - DetailPageConfiguration( - List.unmodifiable([res]), - null, - 0, - "collection", - ), + hw.HomeWidget.widgetClicked.listen( + (uri) => HomeWidgetService.instance.onLaunchFromWidget(uri, context), ); - routeToPage(context, page, forceCustomPageRoute: true).ignore(); } setLocale(Locale newLocale) { diff --git a/mobile/lib/services/home_widget_service.dart b/mobile/lib/services/home_widget_service.dart index 33ef5d2bbc..7b44310c21 100644 --- a/mobile/lib/services/home_widget_service.dart +++ b/mobile/lib/services/home_widget_service.dart @@ -8,9 +8,14 @@ import "package:logging/logging.dart"; import "package:photos/core/configuration.dart"; import "package:photos/core/constants.dart"; import "package:photos/db/files_db.dart"; +import "package:photos/models/collection/collection_items.dart"; import "package:photos/models/file/file_type.dart"; +import "package:photos/services/collections_service.dart"; import "package:photos/services/favorites_service.dart"; +import "package:photos/ui/viewer/file/detail_page.dart"; +import "package:photos/ui/viewer/gallery/collection_page.dart"; import "package:photos/utils/file_util.dart"; +import "package:photos/utils/navigation_util.dart"; import "package:photos/utils/preload_util.dart"; class HomeWidgetService { @@ -171,4 +176,49 @@ class HomeWidgetService { ); _logger.info(">>> SlideshowWidget cleared"); } + + Future onLaunchFromWidget(Uri? uri, BuildContext context) async { + if (uri == null) return; + + final collectionID = + await FavoritesService.instance.getFavoriteCollectionID(); + if (collectionID == null) { + return; + } + + final collection = CollectionsService.instance.getCollectionByID( + collectionID, + ); + if (collection == null) { + return; + } + + final thumbnail = await CollectionsService.instance.getCover(collection); + + final previousGeneratedId = + await hw.HomeWidget.getWidgetData("home_widget_last_img"); + + final res = previousGeneratedId != null + ? await FilesDB.instance.getFile( + previousGeneratedId, + ) + : null; + + routeToPage( + context, + CollectionPage( + CollectionWithThumbnail( + collection, + thumbnail, + ), + ), + ).ignore(); + + if (res == null) return; + + final page = DetailPage( + DetailPageConfiguration(List.unmodifiable([res]), null, 0, "collection"), + ); + routeToPage(context, page, forceCustomPageRoute: true).ignore(); + } } From 896cf0f785aa2973258912e2e609de8e74cb41ce Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 15 Apr 2024 11:50:23 +0530 Subject: [PATCH 29/84] Disable full file caches for now This is only needed for ML indexing, let us revisit this once the ML flow is done instead of adding a premature and possibly disk-space heavy optimization. --- web/apps/photos/src/services/download/index.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/web/apps/photos/src/services/download/index.ts b/web/apps/photos/src/services/download/index.ts index 124d5b4b24..41af5c0557 100644 --- a/web/apps/photos/src/services/download/index.ts +++ b/web/apps/photos/src/services/download/index.ts @@ -7,7 +7,6 @@ import { CustomError } from "@ente/shared/error"; import { Events, eventBus } from "@ente/shared/events"; import { Remote } from "comlink"; import { FILE_TYPE } from "constants/file"; -import isElectron from "is-electron"; import { EnteFile } from "types/file"; import { generateStreamFromArrayBuffer, @@ -89,11 +88,12 @@ class DownloadManagerImpl { e, ); } - try { - if (isElectron()) this.fileCache = await openCache("files"); - } catch (e) { - log.error("Failed to open file cache, will continue without it", e); - } + // TODO (MR): Revisit full file caching cf disk space usage + // try { + // if (isElectron()) this.fileCache = await openCache("files"); + // } catch (e) { + // log.error("Failed to open file cache, will continue without it", e); + // } this.cryptoWorker = await ComlinkCryptoWorker.getInstance(); this.ready = true; eventBus.on(Events.LOGOUT, this.logoutHandler.bind(this), this); From 73ef03a5d9842938d3310b56d158f827c16d2b6c Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 15 Apr 2024 12:14:57 +0530 Subject: [PATCH 30/84] Move read/write whole files into fs --- desktop/src/main/fs.ts | 12 +++--- desktop/src/main/ipc.ts | 44 ++++++++++---------- desktop/src/preload.ts | 36 ++++++++-------- web/apps/photos/src/services/export/index.ts | 9 ++-- web/packages/next/types/ipc.ts | 13 +++++- 5 files changed, 62 insertions(+), 52 deletions(-) diff --git a/desktop/src/main/fs.ts b/desktop/src/main/fs.ts index 11ab360495..94652d93d9 100644 --- a/desktop/src/main/fs.ts +++ b/desktop/src/main/fs.ts @@ -17,6 +17,12 @@ export const fsRmdir = (path: string) => fs.rmdir(path); export const fsRm = (path: string) => fs.rm(path); +export const fsReadTextFile = async (filePath: string) => + fs.readFile(filePath, "utf-8"); + +export const fsWriteTextFile = (path: string, contents: string) => + fs.writeFile(path, contents); + /** * Write a (web) ReadableStream to a file at the given {@link filePath}. * @@ -84,12 +90,6 @@ const writeNodeStream = async ( export const saveStreamToDisk = writeStream; -export const saveFileToDisk = (path: string, contents: string) => - fs.writeFile(path, contents); - -export const readTextFile = async (filePath: string) => - fs.readFile(filePath, "utf-8"); - export const isFolder = async (dirPath: string) => { if (!existsSync(dirPath)) return false; const stats = await fs.stat(dirPath); diff --git a/desktop/src/main/ipc.ts b/desktop/src/main/ipc.ts index 36e13ec60b..17984c1cf0 100644 --- a/desktop/src/main/ipc.ts +++ b/desktop/src/main/ipc.ts @@ -20,12 +20,12 @@ import { import { fsExists, fsMkdirIfNeeded, + fsReadTextFile, fsRename, fsRm, fsRmdir, + fsWriteTextFile, isFolder, - readTextFile, - saveFileToDisk, saveStreamToDisk, } from "./fs"; import { logToDisk } from "./log"; @@ -113,6 +113,26 @@ export const attachIPCHandlers = () => { ipcMain.on("skipAppUpdate", (_, version) => skipAppUpdate(version)); + // - FS + + ipcMain.handle("fsExists", (_, path) => fsExists(path)); + + ipcMain.handle("fsRename", (_, oldPath: string, newPath: string) => + fsRename(oldPath, newPath), + ); + + ipcMain.handle("fsMkdirIfNeeded", (_, dirPath) => fsMkdirIfNeeded(dirPath)); + + ipcMain.handle("fsRmdir", (_, path: string) => fsRmdir(path)); + + ipcMain.handle("fsRm", (_, path: string) => fsRm(path)); + + ipcMain.handle("fsReadTextFile", (_, path: string) => fsReadTextFile(path)); + + ipcMain.handle("fsWriteTextFile", (_, path: string, contents: string) => + fsWriteTextFile(path, contents), + ); + // - Conversion ipcMain.handle("convertToJPEG", (_, fileData, filename) => @@ -164,20 +184,6 @@ export const attachIPCHandlers = () => { ipcMain.handle("showUploadZipDialog", () => showUploadZipDialog()); - // - FS - - ipcMain.handle("fsExists", (_, path) => fsExists(path)); - - ipcMain.handle("fsRename", (_, oldPath: string, newPath: string) => - fsRename(oldPath, newPath), - ); - - ipcMain.handle("fsMkdirIfNeeded", (_, dirPath) => fsMkdirIfNeeded(dirPath)); - - ipcMain.handle("fsRmdir", (_, path: string) => fsRmdir(path)); - - ipcMain.handle("fsRm", (_, path: string) => fsRm(path)); - // - FS Legacy ipcMain.handle( @@ -186,12 +192,6 @@ export const attachIPCHandlers = () => { saveStreamToDisk(path, fileStream), ); - ipcMain.handle("saveFileToDisk", (_, path: string, contents: string) => - saveFileToDisk(path, contents), - ); - - ipcMain.handle("readTextFile", (_, path: string) => readTextFile(path)); - ipcMain.handle("isFolder", (_, dirPath: string) => isFolder(dirPath)); // - Upload diff --git a/desktop/src/preload.ts b/desktop/src/preload.ts index 1a344e832a..057ca9ebb2 100644 --- a/desktop/src/preload.ts +++ b/desktop/src/preload.ts @@ -96,6 +96,8 @@ const skipAppUpdate = (version: string) => { ipcRenderer.send("skipAppUpdate", version); }; +// - FS + const fsExists = (path: string): Promise => ipcRenderer.invoke("fsExists", path); @@ -110,6 +112,12 @@ const fsRmdir = (path: string): Promise => const fsRm = (path: string): Promise => ipcRenderer.invoke("fsRm", path); +const fsReadTextFile = (path: string): Promise => + ipcRenderer.invoke("fsReadTextFile", path); + +const fsWriteTextFile = (path: string, contents: string): Promise => + ipcRenderer.invoke("fsWriteTextFile", path, contents); + // - AUDIT below this // - Conversion @@ -234,12 +242,6 @@ const saveStreamToDisk = ( fileStream: ReadableStream, ): Promise => ipcRenderer.invoke("saveStreamToDisk", path, fileStream); -const saveFileToDisk = (path: string, contents: string): Promise => - ipcRenderer.invoke("saveFileToDisk", path, contents); - -const readTextFile = (path: string): Promise => - ipcRenderer.invoke("readTextFile", path); - const isFolder = (dirPath: string): Promise => ipcRenderer.invoke("isFolder", dirPath); @@ -316,6 +318,17 @@ contextBridge.exposeInMainWorld("electron", { updateOnNextRestart, skipAppUpdate, + // - FS + fs: { + exists: fsExists, + rename: fsRename, + mkdirIfNeeded: fsMkdirIfNeeded, + rmdir: fsRmdir, + rm: fsRm, + readTextFile: fsReadTextFile, + writeTextFile: fsWriteTextFile, + }, + // - Conversion convertToJPEG, generateImageThumbnail, @@ -341,20 +354,9 @@ contextBridge.exposeInMainWorld("electron", { updateWatchMappingSyncedFiles, updateWatchMappingIgnoredFiles, - // - FS - fs: { - exists: fsExists, - rename: fsRename, - mkdirIfNeeded: fsMkdirIfNeeded, - rmdir: fsRmdir, - rm: fsRm, - }, - // - FS legacy // TODO: Move these into fs + document + rename if needed saveStreamToDisk, - saveFileToDisk, - readTextFile, isFolder, // - Upload diff --git a/web/apps/photos/src/services/export/index.ts b/web/apps/photos/src/services/export/index.ts index f7a0c3f3eb..996b911dec 100644 --- a/web/apps/photos/src/services/export/index.ts +++ b/web/apps/photos/src/services/export/index.ts @@ -884,7 +884,7 @@ class ExportService { try { const exportRecord = await this.getExportRecord(folder); const newRecord: ExportRecord = { ...exportRecord, ...newData }; - await ensureElectron().saveFileToDisk( + await ensureElectron().fs.writeTextFile( `${folder}/${exportRecordFileName}`, JSON.stringify(newRecord, null, 2), ); @@ -907,8 +907,7 @@ class ExportService { if (!(await fs.exists(exportRecordJSONPath))) { return this.createEmptyExportRecord(exportRecordJSONPath); } - const recordFile = - await electron.readTextFile(exportRecordJSONPath); + const recordFile = await fs.readTextFile(exportRecordJSONPath); try { return JSON.parse(recordFile); } catch (e) { @@ -1077,7 +1076,7 @@ class ExportService { fileExportName: string, file: EnteFile, ) { - await ensureElectron().saveFileToDisk( + await ensureElectron().fs.writeTextFile( getFileMetadataExportPath(collectionExportPath, fileExportName), getGoogleLikeMetadataFile(fileExportName, file), ); @@ -1106,7 +1105,7 @@ class ExportService { private createEmptyExportRecord = async (exportRecordJSONPath: string) => { const exportRecord: ExportRecord = NULL_EXPORT_RECORD; - await ensureElectron().saveFileToDisk( + await ensureElectron().fs.writeTextFile( exportRecordJSONPath, JSON.stringify(exportRecord, null, 2), ); diff --git a/web/packages/next/types/ipc.ts b/web/packages/next/types/ipc.ts index 69b0c3593c..70e21a10c7 100644 --- a/web/packages/next/types/ipc.ts +++ b/web/packages/next/types/ipc.ts @@ -188,6 +188,17 @@ export interface Electron { * Delete the file at {@link path}. */ rm: (path: string) => Promise; + + /** + * Write a string to a file, replacing the file if it already exists. + * + * @param path The path of the file. + * @param contents The string contents to write. + */ + writeTextFile: (path: string, contents: string) => Promise; + + /** Read the string contents of a file at {@link path}. */ + readTextFile: (path: string) => Promise; }; /* @@ -304,8 +315,6 @@ export interface Electron { path: string, fileStream: ReadableStream, ) => Promise; - saveFileToDisk: (path: string, contents: string) => Promise; - readTextFile: (path: string) => Promise; isFolder: (dirPath: string) => Promise; // - Upload From 3ea4879cf0d7891eb9f27d7988202be2e6ed7480 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 15 Apr 2024 12:20:16 +0530 Subject: [PATCH 31/84] Remove text qualifier The type already enforces that. And it reads better and the call sites this way. --- desktop/src/main/fs.ts | 2 +- desktop/src/main/ipc.ts | 6 +++--- desktop/src/preload.ts | 6 +++--- web/apps/photos/src/services/export/index.ts | 6 +++--- web/packages/next/types/ipc.ts | 8 ++++---- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/desktop/src/main/fs.ts b/desktop/src/main/fs.ts index 94652d93d9..d8cfe7714c 100644 --- a/desktop/src/main/fs.ts +++ b/desktop/src/main/fs.ts @@ -20,7 +20,7 @@ export const fsRm = (path: string) => fs.rm(path); export const fsReadTextFile = async (filePath: string) => fs.readFile(filePath, "utf-8"); -export const fsWriteTextFile = (path: string, contents: string) => +export const fsWriteFile = (path: string, contents: string) => fs.writeFile(path, contents); /** diff --git a/desktop/src/main/ipc.ts b/desktop/src/main/ipc.ts index 17984c1cf0..2a74803020 100644 --- a/desktop/src/main/ipc.ts +++ b/desktop/src/main/ipc.ts @@ -24,7 +24,7 @@ import { fsRename, fsRm, fsRmdir, - fsWriteTextFile, + fsWriteFile, isFolder, saveStreamToDisk, } from "./fs"; @@ -129,8 +129,8 @@ export const attachIPCHandlers = () => { ipcMain.handle("fsReadTextFile", (_, path: string) => fsReadTextFile(path)); - ipcMain.handle("fsWriteTextFile", (_, path: string, contents: string) => - fsWriteTextFile(path, contents), + ipcMain.handle("fsWriteFile", (_, path: string, contents: string) => + fsWriteFile(path, contents), ); // - Conversion diff --git a/desktop/src/preload.ts b/desktop/src/preload.ts index 057ca9ebb2..c709468cbf 100644 --- a/desktop/src/preload.ts +++ b/desktop/src/preload.ts @@ -115,8 +115,8 @@ const fsRm = (path: string): Promise => ipcRenderer.invoke("fsRm", path); const fsReadTextFile = (path: string): Promise => ipcRenderer.invoke("fsReadTextFile", path); -const fsWriteTextFile = (path: string, contents: string): Promise => - ipcRenderer.invoke("fsWriteTextFile", path, contents); +const fsWriteFile = (path: string, contents: string): Promise => + ipcRenderer.invoke("fsWriteFile", path, contents); // - AUDIT below this @@ -326,7 +326,7 @@ contextBridge.exposeInMainWorld("electron", { rmdir: fsRmdir, rm: fsRm, readTextFile: fsReadTextFile, - writeTextFile: fsWriteTextFile, + writeFile: fsWriteFile, }, // - Conversion diff --git a/web/apps/photos/src/services/export/index.ts b/web/apps/photos/src/services/export/index.ts index 996b911dec..165947f04a 100644 --- a/web/apps/photos/src/services/export/index.ts +++ b/web/apps/photos/src/services/export/index.ts @@ -884,7 +884,7 @@ class ExportService { try { const exportRecord = await this.getExportRecord(folder); const newRecord: ExportRecord = { ...exportRecord, ...newData }; - await ensureElectron().fs.writeTextFile( + await ensureElectron().fs.writeFile( `${folder}/${exportRecordFileName}`, JSON.stringify(newRecord, null, 2), ); @@ -1076,7 +1076,7 @@ class ExportService { fileExportName: string, file: EnteFile, ) { - await ensureElectron().fs.writeTextFile( + await ensureElectron().fs.writeFile( getFileMetadataExportPath(collectionExportPath, fileExportName), getGoogleLikeMetadataFile(fileExportName, file), ); @@ -1105,7 +1105,7 @@ class ExportService { private createEmptyExportRecord = async (exportRecordJSONPath: string) => { const exportRecord: ExportRecord = NULL_EXPORT_RECORD; - await ensureElectron().fs.writeTextFile( + await ensureElectron().fs.writeFile( exportRecordJSONPath, JSON.stringify(exportRecord, null, 2), ); diff --git a/web/packages/next/types/ipc.ts b/web/packages/next/types/ipc.ts index 70e21a10c7..60bbb39f8f 100644 --- a/web/packages/next/types/ipc.ts +++ b/web/packages/next/types/ipc.ts @@ -189,16 +189,16 @@ export interface Electron { */ rm: (path: string) => Promise; + /** Read the string contents of a file at {@link path}. */ + readTextFile: (path: string) => Promise; + /** * Write a string to a file, replacing the file if it already exists. * * @param path The path of the file. * @param contents The string contents to write. */ - writeTextFile: (path: string, contents: string) => Promise; - - /** Read the string contents of a file at {@link path}. */ - readTextFile: (path: string) => Promise; + writeFile: (path: string, contents: string) => Promise; }; /* From 0161739bc054374548d93daab40e20d384ca3b57 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 15 Apr 2024 12:41:17 +0530 Subject: [PATCH 32/84] Outline the plan --- desktop/src/main.ts | 20 ++++++++++++++++++++ desktop/src/preload.ts | 3 ++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/desktop/src/main.ts b/desktop/src/main.ts index 4837210c87..10a68003f8 100644 --- a/desktop/src/main.ts +++ b/desktop/src/main.ts @@ -212,6 +212,25 @@ const setupTrayItem = (mainWindow: BrowserWindow) => { tray.setContextMenu(createTrayContextMenu(mainWindow)); }; +/** + * Register a protocol handler that we use for streaming large files between the + * main process (node) and the renderer process (browser) layer. + * + * [Note: IPC streams] + * + * When running without node integration, there is no direct way to pass streams + * across IPC. And passing the entire contents of the file is not feasible for + * large video files because of the memory pressure the copying would entail. + * + * As an alternative, we register a custom protocol handler that can provided a + * bi-directional stream. The renderer can stream data to the node side by + * streaming the request. The node side can stream to the renderer side by + * streaming the response. + * + * See also: [Note: Transferring large amount of data over IPC] + */ +const registerStreamProtocol = () => {}; + /** * Older versions of our app used to maintain a cache dir using the main * process. This has been deprecated in favor of using a normal web cache. @@ -278,6 +297,7 @@ const main = () => { handleDownloads(mainWindow); handleExternalLinks(mainWindow); addAllowOriginHeader(mainWindow); + registerStreamProtocol(); try { deleteLegacyDiskCacheDirIfExists(); diff --git a/desktop/src/preload.ts b/desktop/src/preload.ts index c709468cbf..5603d49a4f 100644 --- a/desktop/src/preload.ts +++ b/desktop/src/preload.ts @@ -300,7 +300,8 @@ const getDirFiles = (dirPath: string): Promise => // https://www.electronjs.org/docs/latest/api/context-bridge#methods // // The copy itself is relatively fast, but the problem with transfering large -// amounts of data is potentially running out of memory during the copy. +// amounts of data is potentially running out of memory during the copy. For an +// alternative, see [Note: IPC streams]. contextBridge.exposeInMainWorld("electron", { // - General appVersion, From 89b832d21fcaf93e6757a03fd3d6a1268e1f6913 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 15 Apr 2024 12:46:40 +0530 Subject: [PATCH 33/84] Baby's first steps --- desktop/src/main.ts | 9 +++++++-- web/apps/photos/src/services/export/index.ts | 11 +++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/desktop/src/main.ts b/desktop/src/main.ts index 10a68003f8..96b49256b8 100644 --- a/desktop/src/main.ts +++ b/desktop/src/main.ts @@ -9,7 +9,7 @@ * https://www.electronjs.org/docs/latest/tutorial/process-model#the-main-process */ import { nativeImage } from "electron"; -import { app, BrowserWindow, Menu, Tray } from "electron/main"; +import { app, BrowserWindow, Menu, protocol, Tray } from "electron/main"; import serveNextAt from "next-electron-server"; import { existsSync } from "node:fs"; import fs from "node:fs/promises"; @@ -229,7 +229,12 @@ const setupTrayItem = (mainWindow: BrowserWindow) => { * * See also: [Note: Transferring large amount of data over IPC] */ -const registerStreamProtocol = () => {}; +const registerStreamProtocol = () => { + protocol.handle("stream", (request: Request) => { + log.info({ e: "Got incoming stream", request }); + return new Response("", { status: 200 }); + }); +}; /** * Older versions of our app used to maintain a cache dir using the main diff --git a/web/apps/photos/src/services/export/index.ts b/web/apps/photos/src/services/export/index.ts index 165947f04a..1a4d339aa5 100644 --- a/web/apps/photos/src/services/export/index.ts +++ b/web/apps/photos/src/services/export/index.ts @@ -1,4 +1,5 @@ import { ensureElectron } from "@/next/electron"; +import { isDevBuild } from "@/next/env"; import log from "@/next/log"; import { CustomError } from "@ente/shared/error"; import { Events, eventBus } from "@ente/shared/events"; @@ -992,6 +993,16 @@ class ExportService { fileExportName, file, ); + // TODO(MR): Productionalize + if (isDevBuild) { + console.log({ a: "will send req", updatedFileStream }); + const req = new Request("stream://foo", { + method: "POST", + body: updatedFileStream, + }); + const res = await fetch(req); + console.log({ a: "got res", res }); + } await electron.saveStreamToDisk( `${collectionExportPath}/${fileExportName}`, updatedFileStream, From 9eab93cfdf29c92dd4e570a01b2698000300d60f Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 15 Apr 2024 13:43:02 +0530 Subject: [PATCH 34/84] Suppress webpack's critical dependency warnings for libheif MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Supressing it for now since it obscures other important information in the console. Upstream issue, which currently doesn't have a workaround: https://github.com/catdad-experiments/libheif-js/issues/23 Full error message: ⚠ ../../node_modules/libheif-js/libheif-wasm/libheif-bundle.js Critical dependency: require function is used in a way in which dependencies cannot be statically extracted Import trace for requested module: ../../node_modules/libheif-js/libheif-wasm/libheif-bundle.js ../../node_modules/libheif-js/wasm-bundle.js ../../node_modules/heic-decode/index.js ../../node_modules/heic-convert/index.js ./src/worker/convert.worker.ts ./src/utils/comlink/ComlinkConvertWorker.ts ./src/services/heic-convert/service.ts ... Refs: - https://stackoverflow.com/questions/38392697/webpack-umd-critical-dependency-cannot-be-statically-extracted --- web/packages/next/next.config.base.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/web/packages/next/next.config.base.js b/web/packages/next/next.config.base.js index f0d1481b40..a3076fa5cd 100644 --- a/web/packages/next/next.config.base.js +++ b/web/packages/next/next.config.base.js @@ -59,11 +59,21 @@ const nextConfig = { GIT_SHA: gitSHA(), }, - // https://dev.to/marcinwosinek/how-to-add-resolve-fallback-to-webpack-5-in-nextjs-10-i6j + // Customize the webpack configuration used by Next.js webpack: (config, { isServer }) => { + // https://dev.to/marcinwosinek/how-to-add-resolve-fallback-to-webpack-5-in-nextjs-10-i6j if (!isServer) { config.resolve.fallback.fs = false; } + + // Suppress the warning "Critical dependency: require function is used + // in a way in which dependencies cannot be statically extracted" when + // import heic-convert. + // + // Upstream issue, which currently doesn't have a workaround. + // https://github.com/catdad-experiments/libheif-js/issues/23 + config.ignoreWarnings = [{ module: /libheif-js/ }]; + return config; }, }; From 2a425b0f9bd1c8d17f13a23bc1b28fbc4add9acf Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 15 Apr 2024 14:22:00 +0530 Subject: [PATCH 35/84] Add duplex parameter to a streaming request Attempt to solve the following error in the browser's console when trying to make the request: [error] download and save failed: TypeError: Failed to construct 'Request': The `duplex` member must be specified for a request with a streaming body --- web/apps/photos/src/services/export/index.ts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/web/apps/photos/src/services/export/index.ts b/web/apps/photos/src/services/export/index.ts index 1a4d339aa5..99e2ac1a81 100644 --- a/web/apps/photos/src/services/export/index.ts +++ b/web/apps/photos/src/services/export/index.ts @@ -996,10 +996,26 @@ class ExportService { // TODO(MR): Productionalize if (isDevBuild) { console.log({ a: "will send req", updatedFileStream }); + // The duplex parameter needs to be set to 'half' when + // streaming requests. + // + // Currently browsers, and specifically in our case, + // since this code runs only within our desktop + // (Electron) app, Chromium, don't support 'full' duplex + // mode (i.e. streaming both the request and the + // response). + // + // https://developer.chrome.com/docs/capabilities/web-apis/fetch-streaming-requests + // + // In another twist, the TypeScript libdom.d.ts does not + // include the "duplex" parameter, so we need to cast to + // get TypeScript to let this code through. e.g. see + // https://github.com/node-fetch/node-fetch/issues/1769 const req = new Request("stream://foo", { method: "POST", body: updatedFileStream, - }); + duplex: "half", + } as unknown as RequestInit); const res = await fetch(req); console.log({ a: "got res", res }); } From 223a4ffcfdf229a66d23e7019ba48dd499c0b9a6 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 15 Apr 2024 15:00:59 +0530 Subject: [PATCH 36/84] [mob][photos] Upgrade connectivity_plus pkg --- mobile/ios/Podfile.lock | 18 ++---- mobile/ios/Runner.xcodeproj/project.pbxproj | 4 -- .../frameworks/ml_framework.dart | 3 +- mobile/lib/services/sync_service.dart | 4 +- mobile/pubspec.lock | 56 ++----------------- mobile/pubspec.yaml | 8 +-- 6 files changed, 13 insertions(+), 80 deletions(-) diff --git a/mobile/ios/Podfile.lock b/mobile/ios/Podfile.lock index 09f9ded3cb..102c04e6ae 100644 --- a/mobile/ios/Podfile.lock +++ b/mobile/ios/Podfile.lock @@ -3,12 +3,9 @@ PODS: - Flutter - battery_info (0.0.1): - Flutter - - bonsoir_darwin (3.0.0): - - Flutter - - FlutterMacOS - connectivity_plus (0.0.1): - Flutter - - ReachabilitySwift + - FlutterMacOS - device_info_plus (0.0.1): - Flutter - file_saver (0.0.1): @@ -171,7 +168,6 @@ PODS: - Flutter - FlutterMacOS - PromisesObjC (2.4.0) - - ReachabilitySwift (5.2.1) - receive_sharing_intent (1.6.8): - Flutter - screen_brightness_ios (0.1.0): @@ -231,8 +227,7 @@ PODS: DEPENDENCIES: - background_fetch (from `.symlinks/plugins/background_fetch/ios`) - battery_info (from `.symlinks/plugins/battery_info/ios`) - - bonsoir_darwin (from `.symlinks/plugins/bonsoir_darwin/darwin`) - - connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`) + - connectivity_plus (from `.symlinks/plugins/connectivity_plus/darwin`) - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`) - file_saver (from `.symlinks/plugins/file_saver/ios`) - firebase_core (from `.symlinks/plugins/firebase_core/ios`) @@ -296,7 +291,6 @@ SPEC REPOS: - onnxruntime-objc - OrderedSet - PromisesObjC - - ReachabilitySwift - SDWebImage - SDWebImageWebPCoder - Sentry @@ -309,10 +303,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/background_fetch/ios" battery_info: :path: ".symlinks/plugins/battery_info/ios" - bonsoir_darwin: - :path: ".symlinks/plugins/bonsoir_darwin/darwin" connectivity_plus: - :path: ".symlinks/plugins/connectivity_plus/ios" + :path: ".symlinks/plugins/connectivity_plus/darwin" device_info_plus: :path: ".symlinks/plugins/device_info_plus/ios" file_saver: @@ -409,8 +401,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: background_fetch: 2319bf7e18237b4b269430b7f14d177c0df09c5a battery_info: 09f5c9ee65394f2291c8c6227bedff345b8a730c - bonsoir_darwin: 127bdc632fdc154ae2f277a4d5c86a6212bc75be - connectivity_plus: 07c49e96d7fc92bc9920617b83238c4d178b446a + connectivity_plus: ddd7f30999e1faaef5967c23d5b6d503d10434db device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6 file_saver: 503e386464dbe118f630e17b4c2e1190fa0cf808 Firebase: 797fd7297b7e1be954432743a0b3f90038e45a71 @@ -458,7 +449,6 @@ SPEC CHECKSUMS: permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2 photo_manager: 4f6810b7dfc4feb03b461ac1a70dacf91fba7604 PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 - ReachabilitySwift: 5ae15e16814b5f9ef568963fb2c87aeb49158c66 receive_sharing_intent: 6837b01768e567fe8562182397bf43d63d8c6437 screen_brightness_ios: 715ca807df953bf676d339f11464e438143ee625 SDWebImage: 40b0b4053e36c660a764958bff99eed16610acbb diff --git a/mobile/ios/Runner.xcodeproj/project.pbxproj b/mobile/ios/Runner.xcodeproj/project.pbxproj index 72c5ef5cf3..89c4926296 100644 --- a/mobile/ios/Runner.xcodeproj/project.pbxproj +++ b/mobile/ios/Runner.xcodeproj/project.pbxproj @@ -285,7 +285,6 @@ "${BUILT_PRODUCTS_DIR}/Mantle/Mantle.framework", "${BUILT_PRODUCTS_DIR}/OrderedSet/OrderedSet.framework", "${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework", - "${BUILT_PRODUCTS_DIR}/ReachabilitySwift/Reachability.framework", "${BUILT_PRODUCTS_DIR}/SDWebImage/SDWebImage.framework", "${BUILT_PRODUCTS_DIR}/SDWebImageWebPCoder/SDWebImageWebPCoder.framework", "${BUILT_PRODUCTS_DIR}/Sentry/Sentry.framework", @@ -293,7 +292,6 @@ "${BUILT_PRODUCTS_DIR}/Toast/Toast.framework", "${BUILT_PRODUCTS_DIR}/background_fetch/background_fetch.framework", "${BUILT_PRODUCTS_DIR}/battery_info/battery_info.framework", - "${BUILT_PRODUCTS_DIR}/bonsoir_darwin/bonsoir_darwin.framework", "${BUILT_PRODUCTS_DIR}/connectivity_plus/connectivity_plus.framework", "${BUILT_PRODUCTS_DIR}/device_info_plus/device_info_plus.framework", "${BUILT_PRODUCTS_DIR}/file_saver/file_saver.framework", @@ -369,7 +367,6 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Mantle.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OrderedSet.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBLPromises.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Reachability.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImage.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImageWebPCoder.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Sentry.framework", @@ -377,7 +374,6 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Toast.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/background_fetch.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/battery_info.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/bonsoir_darwin.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/connectivity_plus.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/device_info_plus.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/file_saver.framework", diff --git a/mobile/lib/services/machine_learning/semantic_search/frameworks/ml_framework.dart b/mobile/lib/services/machine_learning/semantic_search/frameworks/ml_framework.dart index 3abd57db70..ef277a0714 100644 --- a/mobile/lib/services/machine_learning/semantic_search/frameworks/ml_framework.dart +++ b/mobile/lib/services/machine_learning/semantic_search/frameworks/ml_framework.dart @@ -4,7 +4,6 @@ import "dart:io"; import "package:connectivity_plus/connectivity_plus.dart"; import "package:logging/logging.dart"; import "package:photos/core/errors.dart"; - import "package:photos/core/event_bus.dart"; import "package:photos/events/event.dart"; import "package:photos/services/remote_assets_service.dart"; @@ -23,7 +22,7 @@ abstract class MLFramework { MLFramework(this.shouldDownloadOverMobileData) { Connectivity() .onConnectivityChanged - .listen((ConnectivityResult result) async { + .listen((List result) async { _logger.info("Connectivity changed to $result"); if (_state == InitializationState.waitingForNetwork && await _canDownload()) { diff --git a/mobile/lib/services/sync_service.dart b/mobile/lib/services/sync_service.dart index 057e600df8..873270f349 100644 --- a/mobile/lib/services/sync_service.dart +++ b/mobile/lib/services/sync_service.dart @@ -45,7 +45,9 @@ class SyncService { sync(); }); - Connectivity().onConnectivityChanged.listen((ConnectivityResult result) { + Connectivity() + .onConnectivityChanged + .listen((List result) { _logger.info("Connectivity change detected " + result.toString()); if (Configuration.instance.hasConfiguredAccount()) { sync(); diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index ccb0775d7a..bab6f37caa 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -113,38 +113,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.6" - bonsoir: - dependency: transitive - description: - name: bonsoir - sha256: "800d77c0581fff06cc43ef2b7723dfe5ee9b899ab0fdf80fb1c7b8829a5deb5c" - url: "https://pub.dev" - source: hosted - version: "3.0.0+1" - bonsoir_android: - dependency: transitive - description: - name: bonsoir_android - sha256: "7207c36fd7e0f3c7c2d8cf353f02bd640d96e2387d575837f8ac051c9cbf4aa7" - url: "https://pub.dev" - source: hosted - version: "3.0.0+1" - bonsoir_darwin: - dependency: transitive - description: - name: bonsoir_darwin - sha256: "7211042c85da2d6efa80c0976bbd9568f2b63624097779847548ed4530675ade" - url: "https://pub.dev" - source: hosted - version: "3.0.0" - bonsoir_platform_interface: - dependency: transitive - description: - name: bonsoir_platform_interface - sha256: "64d57cd52bd477b4891e9b9d419e6408da171ed9e0efc8aa716e7e343d5d93ad" - url: "https://pub.dev" - source: hosted - version: "3.0.0" boolean_selector: dependency: transitive description: @@ -241,14 +209,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" - cast: - dependency: "direct main" - description: - name: cast - sha256: b70f6be547a53481dffec93ad3cc4974fae5ed707f0b677d4a50c329d7299b98 - url: "https://pub.dev" - source: hosted - version: "2.0.0" characters: dependency: transitive description: @@ -326,18 +286,18 @@ packages: dependency: "direct main" description: name: connectivity_plus - sha256: "77a180d6938f78ca7d2382d2240eb626c0f6a735d0bfdce227d8ffb80f95c48b" + sha256: ebe15d94de9dd7c31dc2ac54e42780acdf3384b1497c69290c9f3c5b0279fc57 url: "https://pub.dev" source: hosted - version: "4.0.2" + version: "6.0.2" connectivity_plus_platform_interface: dependency: transitive description: name: connectivity_plus_platform_interface - sha256: cf1d1c28f4416f8c654d7dc3cd638ec586076255d407cef3ddbdaf178272a71a + sha256: b6a56efe1e6675be240de39107281d4034b64ac23438026355b4234042a35adb url: "https://pub.dev" source: hosted - version: "1.2.4" + version: "2.0.0" convert: dependency: transitive description: @@ -1769,14 +1729,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.0" - protobuf: - dependency: transitive - description: - name: protobuf - sha256: "68645b24e0716782e58948f8467fd42a880f255096a821f9e7d0ec625b00c84d" - url: "https://pub.dev" - source: hosted - version: "3.1.0" provider: dependency: "direct main" description: diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index 3be873cc51..f1575bdf8b 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -27,7 +27,6 @@ dependencies: battery_info: ^1.1.1 bip39: ^1.0.6 cached_network_image: ^3.0.0 - cast: ^2.0.0 chewie: git: url: https://github.com/ente-io/chewie.git @@ -37,11 +36,7 @@ dependencies: collection: # dart computer: git: "https://github.com/ente-io/computer.git" - connectivity_plus: - git: - url: https://github.com/ente-io/plus_plugins.git - ref: check_mobile_first - path: packages/connectivity_plus/connectivity_plus/ + connectivity_plus: ^6.0.2 cross_file: ^0.3.3 crypto: ^3.0.2 cupertino_icons: ^1.0.0 @@ -175,7 +170,6 @@ dependencies: xml: ^6.3.0 dependency_overrides: - connectivity_plus: ^4.0.0 # Remove this after removing dependency from flutter_sodium. # Newer flutter packages depends on ffi > 2.0.0 while flutter_sodium depends on ffi < 2.0.0 ffi: 2.1.0 From ab1ac9cf1121a3a75eafbbb854116c95ce95db24 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 15 Apr 2024 15:04:10 +0530 Subject: [PATCH 37/84] [mob][lint] error on unrelated_type_equality_checks rule voilation --- mobile/analysis_options.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mobile/analysis_options.yaml b/mobile/analysis_options.yaml index cebeb1391e..f30be877bd 100644 --- a/mobile/analysis_options.yaml +++ b/mobile/analysis_options.yaml @@ -22,6 +22,7 @@ linter: - use_key_in_widget_constructors - cancel_subscriptions + - avoid_empty_else - exhaustive_cases @@ -59,6 +60,7 @@ analyzer: prefer_final_locals: warning unnecessary_const: error cancel_subscriptions: error + unrelated_type_equality_checks: error unawaited_futures: warning # convert to warning after fixing existing issues From 057fe9bbb1a31d2a4e132b4f232aa917ad71b3a9 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 15 Apr 2024 15:05:00 +0530 Subject: [PATCH 38/84] Allow fetches for "stream" Ref: - https://github.com/electron/electron/issues/40362 --- desktop/src/main.ts | 76 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 65 insertions(+), 11 deletions(-) diff --git a/desktop/src/main.ts b/desktop/src/main.ts index 96b49256b8..a14fb5d79f 100644 --- a/desktop/src/main.ts +++ b/desktop/src/main.ts @@ -58,6 +58,21 @@ export const allowWindowClose = (): void => { shouldAllowWindowClose = true; }; +/** + * Log a standard startup banner. + * + * This helps us identify app starts and other environment details in the logs. + */ +const logStartupBanner = () => { + const version = isDev ? "dev" : app.getVersion(); + log.info(`Starting ente-photos-desktop ${version}`); + + const platform = process.platform; + const osRelease = os.release(); + const systemVersion = process.getSystemVersion(); + log.info("Running on", { platform, osRelease, systemVersion }); +}; + /** * next-electron-server allows up to directly use the output of `next build` in * production mode and `next dev` in development mode, whilst keeping the rest @@ -74,18 +89,53 @@ export const allowWindowClose = (): void => { const setupRendererServer = () => serveNextAt(rendererURL); /** - * Log a standard startup banner. + * Register privileged schemes. * - * This helps us identify app starts and other environment details in the logs. + * We have two priviliged schemes: + * + * 1. "ente", used for serving our web app (@see {@link setupRendererServer}). + * + * 2. "stream", used for streaming IPC (@see {@link registerStreamProtocol}). + * + * Both of these need some privileges, however, the documentation for Electron's + * registerSchemesAsPrivileged says: + * + * > This method ... can be called only once. + * > + * > https://www.electronjs.org/docs/latest/api/protocol#protocolisprotocolregisteredscheme-deprecated + * + * The library we use for the "ente" scheme already calls it once when we invoke + * {@link setupRendererServer}. Luckily, in practice it seems that the last call + * wins, and we don't need to modify the next-electron-server to prevent it from + * calling registerSchemesAsPrivileged. Instead, both schemes get registered + * fine, but we do need to repeat what next-electron-server had done. */ -const logStartupBanner = () => { - const version = isDev ? "dev" : app.getVersion(); - log.info(`Starting ente-photos-desktop ${version}`); - - const platform = process.platform; - const osRelease = os.release(); - const systemVersion = process.getSystemVersion(); - log.info("Running on", { platform, osRelease, systemVersion }); +const registerPrivilegedSchemes = () => { + protocol.registerSchemesAsPrivileged([ + { + scheme: "ente", + privileges: { + standard: true, + secure: true, + allowServiceWorkers: true, + supportFetchAPI: true, + corsEnabled: true, + }, + }, + { + scheme: "stream", + privileges: { + // standard: true, + // secure: true, + // supportFetchAPI: true, + standard: true, + secure: true, + allowServiceWorkers: true, + supportFetchAPI: true, + corsEnabled: true, + }, + }, + ]); }; /** @@ -228,6 +278,8 @@ const setupTrayItem = (mainWindow: BrowserWindow) => { * streaming the response. * * See also: [Note: Transferring large amount of data over IPC] + * + * Depends on: {@link registerPrivilegedSchemes} */ const registerStreamProtocol = () => { protocol.handle("stream", (request: Request) => { @@ -275,8 +327,10 @@ const main = () => { let mainWindow: BrowserWindow | undefined; initLogging(); - setupRendererServer(); logStartupBanner(); + // The order of the next two calls is important + setupRendererServer(); + registerPrivilegedSchemes(); increaseDiskCache(); app.on("second-instance", () => { From 5bac629c2b088ef2b2f19ceeacdd4b193ca840ee Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 15 Apr 2024 15:09:24 +0530 Subject: [PATCH 39/84] [mob][photos] Fix connectivityResult check --- .../semantic_search/frameworks/ml_framework.dart | 8 +++++--- mobile/lib/utils/file_uploader.dart | 5 +++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/mobile/lib/services/machine_learning/semantic_search/frameworks/ml_framework.dart b/mobile/lib/services/machine_learning/semantic_search/frameworks/ml_framework.dart index ef277a0714..d3736d7680 100644 --- a/mobile/lib/services/machine_learning/semantic_search/frameworks/ml_framework.dart +++ b/mobile/lib/services/machine_learning/semantic_search/frameworks/ml_framework.dart @@ -134,9 +134,11 @@ abstract class MLFramework { } Future _canDownload() async { - final connectivityResult = await (Connectivity().checkConnectivity()); - return connectivityResult != ConnectivityResult.mobile || - shouldDownloadOverMobileData; + final List connections = + await (Connectivity().checkConnectivity()); + final bool isConnectedToMobile = + connections.contains(ConnectivityResult.mobile); + return !isConnectedToMobile || shouldDownloadOverMobileData; } } diff --git a/mobile/lib/utils/file_uploader.dart b/mobile/lib/utils/file_uploader.dart index a545605e99..d877ce522c 100644 --- a/mobile/lib/utils/file_uploader.dart +++ b/mobile/lib/utils/file_uploader.dart @@ -355,9 +355,10 @@ class FileUploader { if (isForceUpload) { return; } - final connectivityResult = await (Connectivity().checkConnectivity()); + final List connections = + await (Connectivity().checkConnectivity()); bool canUploadUnderCurrentNetworkConditions = true; - if (connectivityResult == ConnectivityResult.mobile) { + if (connections.any((element) => element == ConnectivityResult.mobile)) { canUploadUnderCurrentNetworkConditions = Configuration.instance.shouldBackupOverMobileData(); } From 720e84ba1f210ed516cec18d89f002da6bd3828d Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 15 Apr 2024 15:23:01 +0530 Subject: [PATCH 40/84] Prune Refs: - https://www.electronjs.org/docs/latest/api/protocol - https://github.com/electron/electron/issues/39031 - https://github.com/electron/electron/issues/38749 --- desktop/src/main.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/desktop/src/main.ts b/desktop/src/main.ts index a14fb5d79f..a8c94aa309 100644 --- a/desktop/src/main.ts +++ b/desktop/src/main.ts @@ -113,6 +113,7 @@ const setupRendererServer = () => serveNextAt(rendererURL); const registerPrivilegedSchemes = () => { protocol.registerSchemesAsPrivileged([ { + // Taken verbatim from next-electron-server's code (index.js) scheme: "ente", privileges: { standard: true, @@ -125,14 +126,15 @@ const registerPrivilegedSchemes = () => { { scheme: "stream", privileges: { - // standard: true, + // TODO(MR): Remove the commented bits if we don't end up + // needing them by the time the IPC refactoring is done. + + // Prevent the insecure origin issues when fetching this // secure: true, - // supportFetchAPI: true, - standard: true, - secure: true, - allowServiceWorkers: true, + // Allow the web fetch API in the renderer to use this scheme. supportFetchAPI: true, - corsEnabled: true, + // Allow it to be used with video tags. + // stream: true, }, }, ]); From 0881212e4fc57d44c867ecaf69b696c18d437117 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 15 Apr 2024 15:40:50 +0530 Subject: [PATCH 41/84] Rearrange --- desktop/src/main.ts | 54 ++++-------- desktop/src/main/fs.ts | 67 +------------- desktop/src/main/services/ffmpeg.ts | 2 +- desktop/src/main/services/imageProcessor.ts | 2 +- desktop/src/main/services/ml-clip.ts | 2 +- desktop/src/main/services/ml.ts | 2 +- desktop/src/main/stream.ts | 97 +++++++++++++++++++++ 7 files changed, 118 insertions(+), 108 deletions(-) create mode 100644 desktop/src/main/stream.ts diff --git a/desktop/src/main.ts b/desktop/src/main.ts index a8c94aa309..8526e23632 100644 --- a/desktop/src/main.ts +++ b/desktop/src/main.ts @@ -27,6 +27,7 @@ import { setupAutoUpdater } from "./main/services/app-update"; import autoLauncher from "./main/services/autoLauncher"; import { initWatcher } from "./main/services/chokidar"; import { userPreferences } from "./main/stores/user-preferences"; +import { registerStreamProtocol } from "./main/stream"; import { isDev } from "./main/util"; /** @@ -91,24 +92,26 @@ const setupRendererServer = () => serveNextAt(rendererURL); /** * Register privileged schemes. * - * We have two priviliged schemes: + * We have two privileged schemes: * * 1. "ente", used for serving our web app (@see {@link setupRendererServer}). * * 2. "stream", used for streaming IPC (@see {@link registerStreamProtocol}). * * Both of these need some privileges, however, the documentation for Electron's - * registerSchemesAsPrivileged says: + * [registerSchemesAsPrivileged](https://www.electronjs.org/docs/latest/api/protocol) + * says: * * > This method ... can be called only once. - * > - * > https://www.electronjs.org/docs/latest/api/protocol#protocolisprotocolregisteredscheme-deprecated * - * The library we use for the "ente" scheme already calls it once when we invoke - * {@link setupRendererServer}. Luckily, in practice it seems that the last call - * wins, and we don't need to modify the next-electron-server to prevent it from - * calling registerSchemesAsPrivileged. Instead, both schemes get registered - * fine, but we do need to repeat what next-electron-server had done. + * The library we use for the "ente" scheme, next-electron-server, already calls + * it once when we invoke {@link setupRendererServer}. + * + * In practice calling it multiple times just causes the values to be + * overwritten, and the last call wins. So we don't need to modify + * next-electron-server to prevent it from calling registerSchemesAsPrivileged. + * Instead, we (a) repeat what next-electron-server had done here, and (b) + * ensure that we're called after {@link setupRendererServer}. */ const registerPrivilegedSchemes = () => { protocol.registerSchemesAsPrivileged([ @@ -264,32 +267,6 @@ const setupTrayItem = (mainWindow: BrowserWindow) => { tray.setContextMenu(createTrayContextMenu(mainWindow)); }; -/** - * Register a protocol handler that we use for streaming large files between the - * main process (node) and the renderer process (browser) layer. - * - * [Note: IPC streams] - * - * When running without node integration, there is no direct way to pass streams - * across IPC. And passing the entire contents of the file is not feasible for - * large video files because of the memory pressure the copying would entail. - * - * As an alternative, we register a custom protocol handler that can provided a - * bi-directional stream. The renderer can stream data to the node side by - * streaming the request. The node side can stream to the renderer side by - * streaming the response. - * - * See also: [Note: Transferring large amount of data over IPC] - * - * Depends on: {@link registerPrivilegedSchemes} - */ -const registerStreamProtocol = () => { - protocol.handle("stream", (request: Request) => { - log.info({ e: "Got incoming stream", request }); - return new Response("", { status: 200 }); - }); -}; - /** * Older versions of our app used to maintain a cache dir using the main * process. This has been deprecated in favor of using a normal web cache. @@ -349,16 +326,15 @@ const main = () => { // Note that some Electron APIs can only be used after this event occurs. app.on("ready", async () => { mainWindow = await createMainWindow(); - const watcher = initWatcher(mainWindow); - setupTrayItem(mainWindow); Menu.setApplicationMenu(await createApplicationMenu(mainWindow)); + setupTrayItem(mainWindow); attachIPCHandlers(); - attachFSWatchIPCHandlers(watcher); + attachFSWatchIPCHandlers(initWatcher(mainWindow)); + registerStreamProtocol(); if (!isDev) setupAutoUpdater(mainWindow); handleDownloads(mainWindow); handleExternalLinks(mainWindow); addAllowOriginHeader(mainWindow); - registerStreamProtocol(); try { deleteLegacyDiskCacheDirIfExists(); diff --git a/desktop/src/main/fs.ts b/desktop/src/main/fs.ts index d8cfe7714c..a870a7ab5f 100644 --- a/desktop/src/main/fs.ts +++ b/desktop/src/main/fs.ts @@ -1,9 +1,9 @@ /** * @file file system related functions exposed over the context bridge. */ -import { createWriteStream, existsSync } from "node:fs"; +import { existsSync } from "node:fs"; import fs from "node:fs/promises"; -import { Readable } from "node:stream"; +import { writeStream } from "./stream"; export const fsExists = (path: string) => existsSync(path); @@ -23,69 +23,6 @@ export const fsReadTextFile = async (filePath: string) => export const fsWriteFile = (path: string, contents: string) => fs.writeFile(path, contents); -/** - * Write a (web) ReadableStream to a file at the given {@link filePath}. - * - * The returned promise resolves when the write completes. - * - * @param filePath The local filesystem path where the file should be written. - * @param readableStream A [web - * ReadableStream](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) - */ -export const writeStream = (filePath: string, readableStream: ReadableStream) => - writeNodeStream(filePath, convertWebReadableStreamToNode(readableStream)); - -/** - * Convert a Web ReadableStream into a Node.js ReadableStream - * - * This can be used to, for example, write a ReadableStream obtained via - * `net.fetch` into a file using the Node.js `fs` APIs - */ -const convertWebReadableStreamToNode = (readableStream: ReadableStream) => { - const reader = readableStream.getReader(); - const rs = new Readable(); - - rs._read = async () => { - try { - const result = await reader.read(); - - if (!result.done) { - rs.push(Buffer.from(result.value)); - } else { - rs.push(null); - return; - } - } catch (e) { - rs.emit("error", e); - } - }; - - return rs; -}; - -const writeNodeStream = async ( - filePath: string, - fileStream: NodeJS.ReadableStream, -) => { - const writeable = createWriteStream(filePath); - - fileStream.on("error", (error) => { - writeable.destroy(error); // Close the writable stream with an error - }); - - fileStream.pipe(writeable); - - await new Promise((resolve, reject) => { - writeable.on("finish", resolve); - writeable.on("error", async (e: unknown) => { - if (existsSync(filePath)) { - await fs.unlink(filePath); - } - reject(e); - }); - }); -}; - /* TODO: Audit below this */ export const saveStreamToDisk = writeStream; diff --git a/desktop/src/main/services/ffmpeg.ts b/desktop/src/main/services/ffmpeg.ts index e9639a26f8..3072d5ee7b 100644 --- a/desktop/src/main/services/ffmpeg.ts +++ b/desktop/src/main/services/ffmpeg.ts @@ -2,7 +2,7 @@ import pathToFfmpeg from "ffmpeg-static"; import { existsSync } from "node:fs"; import fs from "node:fs/promises"; import { ElectronFile } from "../../types/ipc"; -import { writeStream } from "../fs"; +import { writeStream } from "../stream"; import log from "../log"; import { generateTempFilePath, getTempDirPath } from "../temp"; import { execAsync } from "../util"; diff --git a/desktop/src/main/services/imageProcessor.ts b/desktop/src/main/services/imageProcessor.ts index 890e0e6347..d87fb0c5f2 100644 --- a/desktop/src/main/services/imageProcessor.ts +++ b/desktop/src/main/services/imageProcessor.ts @@ -2,7 +2,7 @@ import { existsSync } from "fs"; import fs from "node:fs/promises"; import path from "path"; import { CustomErrors, ElectronFile } from "../../types/ipc"; -import { writeStream } from "../fs"; +import { writeStream } from "../stream"; import log from "../log"; import { isPlatform } from "../platform"; import { generateTempFilePath } from "../temp"; diff --git a/desktop/src/main/services/ml-clip.ts b/desktop/src/main/services/ml-clip.ts index 63fa751482..af8198a3cf 100644 --- a/desktop/src/main/services/ml-clip.ts +++ b/desktop/src/main/services/ml-clip.ts @@ -11,7 +11,7 @@ import fs from "node:fs/promises"; import * as ort from "onnxruntime-node"; import Tokenizer from "../../thirdparty/clip-bpe-ts/mod"; import { CustomErrors } from "../../types/ipc"; -import { writeStream } from "../fs"; +import { writeStream } from "../stream"; import log from "../log"; import { generateTempFilePath } from "../temp"; import { deleteTempFile } from "./ffmpeg"; diff --git a/desktop/src/main/services/ml.ts b/desktop/src/main/services/ml.ts index 10402db217..e1d68e2ddd 100644 --- a/desktop/src/main/services/ml.ts +++ b/desktop/src/main/services/ml.ts @@ -15,7 +15,7 @@ import { existsSync } from "fs"; import fs from "node:fs/promises"; import path from "node:path"; import * as ort from "onnxruntime-node"; -import { writeStream } from "../fs"; +import { writeStream } from "../stream"; import log from "../log"; /** diff --git a/desktop/src/main/stream.ts b/desktop/src/main/stream.ts new file mode 100644 index 0000000000..2edf599371 --- /dev/null +++ b/desktop/src/main/stream.ts @@ -0,0 +1,97 @@ +/** + * @file stream data to-from renderer using a custom protocol handler. + */ +import { protocol } from "electron/main"; +import { createWriteStream, existsSync } from "node:fs"; +import fs from "node:fs/promises"; +import { Readable } from "node:stream"; +import log from "./log"; + +/** + * Register a protocol handler that we use for streaming large files between the + * main process (node) and the renderer process (browser) layer. + * + * [Note: IPC streams] + * + * When running without node integration, there is no direct way to pass streams + * across IPC. And passing the entire contents of the file is not feasible for + * large video files because of the memory pressure the copying would entail. + * + * As an alternative, we register a custom protocol handler that can provided a + * bi-directional stream. The renderer can stream data to the node side by + * streaming the request. The node side can stream to the renderer side by + * streaming the response. + * + * See also: [Note: Transferring large amount of data over IPC] + * + * Depends on {@link registerPrivilegedSchemes}. + */ +export const registerStreamProtocol = () => { + protocol.handle("stream", (request: Request) => { + log.info({ e: "Got incoming stream", request }); + return new Response("", { status: 200 }); + }); +}; + +/** + * Write a (web) ReadableStream to a file at the given {@link filePath}. + * + * The returned promise resolves when the write completes. + * + * @param filePath The local filesystem path where the file should be written. + * @param readableStream A [web + * ReadableStream](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) + */ +export const writeStream = (filePath: string, readableStream: ReadableStream) => + writeNodeStream(filePath, convertWebReadableStreamToNode(readableStream)); + +/** + * Convert a Web ReadableStream into a Node.js ReadableStream + * + * This can be used to, for example, write a ReadableStream obtained via + * `net.fetch` into a file using the Node.js `fs` APIs + */ +const convertWebReadableStreamToNode = (readableStream: ReadableStream) => { + const reader = readableStream.getReader(); + const rs = new Readable(); + + rs._read = async () => { + try { + const result = await reader.read(); + + if (!result.done) { + rs.push(Buffer.from(result.value)); + } else { + rs.push(null); + return; + } + } catch (e) { + rs.emit("error", e); + } + }; + + return rs; +}; + +const writeNodeStream = async ( + filePath: string, + fileStream: NodeJS.ReadableStream, +) => { + const writeable = createWriteStream(filePath); + + fileStream.on("error", (error) => { + writeable.destroy(error); // Close the writable stream with an error + }); + + fileStream.pipe(writeable); + + await new Promise((resolve, reject) => { + writeable.on("finish", resolve); + writeable.on("error", async (e: unknown) => { + if (existsSync(filePath)) { + await fs.unlink(filePath); + } + reject(e); + }); + }); +}; From fdb9e4e20513b04aa4c75cd0645bede85add6537 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 15 Apr 2024 15:46:47 +0530 Subject: [PATCH 42/84] [mob][photos] Use modificationTime as creationTime if it's lower than creationTime --- mobile/lib/models/file/file.dart | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/mobile/lib/models/file/file.dart b/mobile/lib/models/file/file.dart index 607988a1b9..75a40c99b0 100644 --- a/mobile/lib/models/file/file.dart +++ b/mobile/lib/models/file/file.dart @@ -85,13 +85,24 @@ class EnteFile { static int parseFileCreationTime(String? fileTitle, AssetEntity asset) { int creationTime = asset.createDateTime.microsecondsSinceEpoch; + final int modificationTime = asset.modifiedDateTime.microsecondsSinceEpoch; if (creationTime >= jan011981Time) { // assuming that fileSystem is returning correct creationTime. // During upload, this might get overridden with exif Creation time + // When the assetModifiedTime is less than creationTime, than just use + // that as creationTime. This is to handle cases where file might be + // copied to the fileSystem from somewhere else See #https://superuser.com/a/1091147 + if (modificationTime >= jan011981Time && + modificationTime < creationTime) { + _logger.info( + 'LocalID: ${asset.id} modification time is less than creation time. Using modification time as creation time', + ); + creationTime = modificationTime; + } return creationTime; } else { - if (asset.modifiedDateTime.microsecondsSinceEpoch >= jan011981Time) { - creationTime = asset.modifiedDateTime.microsecondsSinceEpoch; + if (modificationTime >= jan011981Time) { + creationTime = modificationTime; } else { creationTime = DateTime.now().toUtc().microsecondsSinceEpoch; } @@ -106,7 +117,6 @@ class EnteFile { // ignore } } - return creationTime; } From 4c88f5eec941cc0c198f8f93bd20a9c7a90d1a0f Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 15 Apr 2024 15:53:40 +0530 Subject: [PATCH 43/84] Add write handler --- desktop/src/main/stream.ts | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/desktop/src/main/stream.ts b/desktop/src/main/stream.ts index 2edf599371..5f9ce55732 100644 --- a/desktop/src/main/stream.ts +++ b/desktop/src/main/stream.ts @@ -27,9 +27,26 @@ import log from "./log"; * Depends on {@link registerPrivilegedSchemes}. */ export const registerStreamProtocol = () => { - protocol.handle("stream", (request: Request) => { - log.info({ e: "Got incoming stream", request }); - return new Response("", { status: 200 }); + protocol.handle("stream", async (request: Request) => { + const url = request.url; + const { host, pathname } = new URL(url); + switch (host) { + /* stream://write//path/to/file */ + /* -host/pathname----- */ + case "write": + try { + await writeStream(pathname, request.body); + return new Response("", { status: 200 }); + } catch (e) { + log.error(`Failed to write stream for ${url}`, e); + return new Response( + `Failed to write stream: ${e.message}`, + { status: 500 }, + ); + } + default: + return new Response("", { status: 404 }); + } }); }; From 8cdb31783b4571310d543965c03c1bf8f559b882 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 15 Apr 2024 15:57:57 +0530 Subject: [PATCH 44/84] Enhance --- web/packages/shared/utils/index.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/web/packages/shared/utils/index.ts b/web/packages/shared/utils/index.ts index 1ed02fabee..c027b6cb62 100644 --- a/web/packages/shared/utils/index.ts +++ b/web/packages/shared/utils/index.ts @@ -1,7 +1,11 @@ -export async function sleep(time: number) { - await new Promise((resolve) => { - setTimeout(() => resolve(null), time); - }); +/** + * Wait for {@link ms} milliseconds + * + * This function is a promisified `setTimeout`. It returns a promise that + * resolves after {@link ms} milliseconds. + */ +export async function sleep(ms: number) { + await new Promise((resolve) => setTimeout(resolve, ms)); } export function downloadAsFile(filename: string, content: string) { From a74d904989e97c7f28323acd9506715482667728 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 15 Apr 2024 16:00:25 +0530 Subject: [PATCH 45/84] Use a test stream Example taken from https://developer.chrome.com/docs/capabilities/web-apis/fetch-streaming-requests --- web/apps/photos/src/services/export/index.ts | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/web/apps/photos/src/services/export/index.ts b/web/apps/photos/src/services/export/index.ts index 99e2ac1a81..40bb9345f1 100644 --- a/web/apps/photos/src/services/export/index.ts +++ b/web/apps/photos/src/services/export/index.ts @@ -995,6 +995,19 @@ class ExportService { ); // TODO(MR): Productionalize if (isDevBuild) { + const testStream = new ReadableStream({ + async start(controller) { + await sleep(1000); + controller.enqueue("This "); + await sleep(1000); + controller.enqueue("is "); + await sleep(1000); + controller.enqueue("a "); + await sleep(1000); + controller.enqueue("test"); + controller.close(); + }, + }).pipeThrough(new TextEncoderStream()); console.log({ a: "will send req", updatedFileStream }); // The duplex parameter needs to be set to 'half' when // streaming requests. @@ -1011,9 +1024,10 @@ class ExportService { // include the "duplex" parameter, so we need to cast to // get TypeScript to let this code through. e.g. see // https://github.com/node-fetch/node-fetch/issues/1769 - const req = new Request("stream://foo", { + const req = new Request("stream://write/tmp/foo.txt", { method: "POST", - body: updatedFileStream, + // body: updatedFileStream, + body: testStream, duplex: "half", } as unknown as RequestInit); const res = await fetch(req); From 6b331612b661df3b0a5b818247db968f52585b36 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 15 Apr 2024 18:37:57 +0530 Subject: [PATCH 46/84] writeStream --- web/apps/photos/src/utils/native-stream.ts | 39 ++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 web/apps/photos/src/utils/native-stream.ts diff --git a/web/apps/photos/src/utils/native-stream.ts b/web/apps/photos/src/utils/native-stream.ts new file mode 100644 index 0000000000..b7617e4afa --- /dev/null +++ b/web/apps/photos/src/utils/native-stream.ts @@ -0,0 +1,39 @@ +/** + * @file Streaming IPC communication with the Node.js layer of our desktop app. + * + * NOTE: These functions only work when we're running in our desktop app. + */ + +/** + * Write the given stream to a file on the local machine. + * + * **This only works when we're running in our desktop app**. It uses the + * "stream://" protocol handler exposed by our custom code in the Node.js layer. + * See: [Note: IPC streams]. + * + * @param path The path on the local machine where to write the file to. + * @param stream The stream which should be written into the file. + * */ +export const writeStream = async (path: string, stream: ReadableStream) => { + // The duplex parameter needs to be set to 'half' when streaming requests. + // + // Currently browsers, and specifically in our case, since this code runs + // only within our desktop (Electron) app, Chromium, don't support 'full' + // duplex mode (i.e. streaming both the request and the response). + // https://developer.chrome.com/docs/capabilities/web-apis/fetch-streaming-requests + // + // In another twist, the TypeScript libdom.d.ts does not include the + // "duplex" parameter, so we need to cast to get TypeScript to let this code + // through. e.g. see https://github.com/node-fetch/node-fetch/issues/1769 + const req = new Request(`stream://write/${path}`, { + // GET can't have a body + method: "POST", + body: stream, + duplex: "half", + } as unknown as RequestInit); + const res = await fetch(req); + if (!res.ok) + throw new Error( + `Failed to write stream to ${path}: HTTP ${res.status}`, + ); +}; From c99c4ac839da4b3dfa457c626e85cb0c2fa9f8c7 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 15 Apr 2024 19:35:19 +0530 Subject: [PATCH 47/84] Use new method --- web/apps/photos/src/services/export/index.ts | 48 ++------------------ 1 file changed, 4 insertions(+), 44 deletions(-) diff --git a/web/apps/photos/src/services/export/index.ts b/web/apps/photos/src/services/export/index.ts index 40bb9345f1..7d62798823 100644 --- a/web/apps/photos/src/services/export/index.ts +++ b/web/apps/photos/src/services/export/index.ts @@ -1,5 +1,4 @@ import { ensureElectron } from "@/next/electron"; -import { isDevBuild } from "@/next/env"; import log from "@/next/log"; import { CustomError } from "@ente/shared/error"; import { Events, eventBus } from "@ente/shared/events"; @@ -35,6 +34,7 @@ import { mergeMetadata, } from "utils/file"; import { safeDirectoryName, safeFileName } from "utils/native-fs"; +import { writeStream } from "utils/native-stream"; import { getAllLocalCollections } from "../collectionService"; import downloadManager from "../download"; import { getAllLocalFiles } from "../fileService"; @@ -993,47 +993,7 @@ class ExportService { fileExportName, file, ); - // TODO(MR): Productionalize - if (isDevBuild) { - const testStream = new ReadableStream({ - async start(controller) { - await sleep(1000); - controller.enqueue("This "); - await sleep(1000); - controller.enqueue("is "); - await sleep(1000); - controller.enqueue("a "); - await sleep(1000); - controller.enqueue("test"); - controller.close(); - }, - }).pipeThrough(new TextEncoderStream()); - console.log({ a: "will send req", updatedFileStream }); - // The duplex parameter needs to be set to 'half' when - // streaming requests. - // - // Currently browsers, and specifically in our case, - // since this code runs only within our desktop - // (Electron) app, Chromium, don't support 'full' duplex - // mode (i.e. streaming both the request and the - // response). - // - // https://developer.chrome.com/docs/capabilities/web-apis/fetch-streaming-requests - // - // In another twist, the TypeScript libdom.d.ts does not - // include the "duplex" parameter, so we need to cast to - // get TypeScript to let this code through. e.g. see - // https://github.com/node-fetch/node-fetch/issues/1769 - const req = new Request("stream://write/tmp/foo.txt", { - method: "POST", - // body: updatedFileStream, - body: testStream, - duplex: "half", - } as unknown as RequestInit); - const res = await fetch(req); - console.log({ a: "got res", res }); - } - await electron.saveStreamToDisk( + await writeStream( `${collectionExportPath}/${fileExportName}`, updatedFileStream, ); @@ -1084,7 +1044,7 @@ class ExportService { imageExportName, file, ); - await electron.saveStreamToDisk( + await writeStream( `${collectionExportPath}/${imageExportName}`, imageStream, ); @@ -1096,7 +1056,7 @@ class ExportService { file, ); try { - await electron.saveStreamToDisk( + await writeStream( `${collectionExportPath}/${videoExportName}`, videoStream, ); From 67aacf83917962d1114d7d0ec32199d3327e99a3 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 15 Apr 2024 19:39:54 +0530 Subject: [PATCH 48/84] Replace everywhere --- desktop/src/main/fs.ts | 3 -- desktop/src/main/ipc.ts | 7 ----- desktop/src/preload.ts | 6 ---- web/apps/photos/src/utils/file/index.ts | 41 ++++++++++--------------- web/packages/next/types/ipc.ts | 4 --- 5 files changed, 17 insertions(+), 44 deletions(-) diff --git a/desktop/src/main/fs.ts b/desktop/src/main/fs.ts index a870a7ab5f..36de710c34 100644 --- a/desktop/src/main/fs.ts +++ b/desktop/src/main/fs.ts @@ -3,7 +3,6 @@ */ import { existsSync } from "node:fs"; import fs from "node:fs/promises"; -import { writeStream } from "./stream"; export const fsExists = (path: string) => existsSync(path); @@ -25,8 +24,6 @@ export const fsWriteFile = (path: string, contents: string) => /* TODO: Audit below this */ -export const saveStreamToDisk = writeStream; - export const isFolder = async (dirPath: string) => { if (!existsSync(dirPath)) return false; const stats = await fs.stat(dirPath); diff --git a/desktop/src/main/ipc.ts b/desktop/src/main/ipc.ts index 2a74803020..bd29057da0 100644 --- a/desktop/src/main/ipc.ts +++ b/desktop/src/main/ipc.ts @@ -26,7 +26,6 @@ import { fsRmdir, fsWriteFile, isFolder, - saveStreamToDisk, } from "./fs"; import { logToDisk } from "./log"; import { @@ -186,12 +185,6 @@ export const attachIPCHandlers = () => { // - FS Legacy - ipcMain.handle( - "saveStreamToDisk", - (_, path: string, fileStream: ReadableStream) => - saveStreamToDisk(path, fileStream), - ); - ipcMain.handle("isFolder", (_, dirPath: string) => isFolder(dirPath)); // - Upload diff --git a/desktop/src/preload.ts b/desktop/src/preload.ts index 5603d49a4f..ff2cf505af 100644 --- a/desktop/src/preload.ts +++ b/desktop/src/preload.ts @@ -237,11 +237,6 @@ const updateWatchMappingIgnoredFiles = ( // - FS Legacy -const saveStreamToDisk = ( - path: string, - fileStream: ReadableStream, -): Promise => ipcRenderer.invoke("saveStreamToDisk", path, fileStream); - const isFolder = (dirPath: string): Promise => ipcRenderer.invoke("isFolder", dirPath); @@ -357,7 +352,6 @@ contextBridge.exposeInMainWorld("electron", { // - FS legacy // TODO: Move these into fs + document + rename if needed - saveStreamToDisk, isFolder, // - Upload diff --git a/web/apps/photos/src/utils/file/index.ts b/web/apps/photos/src/utils/file/index.ts index 8f72cb4508..785921cc91 100644 --- a/web/apps/photos/src/utils/file/index.ts +++ b/web/apps/photos/src/utils/file/index.ts @@ -53,6 +53,7 @@ import { VISIBILITY_STATE } from "types/magicMetadata"; import { FileTypeInfo } from "types/upload"; import { isArchivedFile, updateMagicMetadata } from "utils/magicMetadata"; import { safeFileName } from "utils/native-fs"; +import { writeStream } from "utils/native-stream"; const WAIT_TIME_IMAGE_CONVERSION = 30 * 1000; @@ -798,55 +799,47 @@ async function downloadFileDesktop( electron: Electron, fileReader: FileReader, file: EnteFile, - downloadPath: string, + downloadDir: string, ) { - const fileStream = (await DownloadManager.getFile( + const fs = electron.fs; + const stream = (await DownloadManager.getFile( file, )) as ReadableStream; - const updatedFileStream = await getUpdatedEXIFFileForDownload( + const updatedStream = await getUpdatedEXIFFileForDownload( fileReader, file, - fileStream, + stream, ); if (file.metadata.fileType === FILE_TYPE.LIVE_PHOTO) { - const fileBlob = await new Response(updatedFileStream).blob(); + const fileBlob = await new Response(updatedStream).blob(); const livePhoto = await decodeLivePhoto(file, fileBlob); const imageExportName = await safeFileName( - downloadPath, + downloadDir, livePhoto.imageNameTitle, - electron.fs.exists, + fs.exists, ); const imageStream = generateStreamFromArrayBuffer(livePhoto.image); - await electron.saveStreamToDisk( - `${downloadPath}/${imageExportName}`, - imageStream, - ); + await writeStream(`${downloadDir}/${imageExportName}`, imageStream); try { const videoExportName = await safeFileName( - downloadPath, + downloadDir, livePhoto.videoNameTitle, - electron.fs.exists, + fs.exists, ); const videoStream = generateStreamFromArrayBuffer(livePhoto.video); - await electron.saveStreamToDisk( - `${downloadPath}/${videoExportName}`, - videoStream, - ); + await writeStream(`${downloadDir}/${videoExportName}`, videoStream); } catch (e) { - await electron.fs.rm(`${downloadPath}/${imageExportName}`); + await fs.rm(`${downloadDir}/${imageExportName}`); throw e; } } else { const fileExportName = await safeFileName( - downloadPath, + downloadDir, file.metadata.title, - electron.fs.exists, - ); - await electron.saveStreamToDisk( - `${downloadPath}/${fileExportName}`, - updatedFileStream, + fs.exists, ); + await writeStream(`${downloadDir}/${fileExportName}`, updatedStream); } } diff --git a/web/packages/next/types/ipc.ts b/web/packages/next/types/ipc.ts index 60bbb39f8f..3477d745e4 100644 --- a/web/packages/next/types/ipc.ts +++ b/web/packages/next/types/ipc.ts @@ -311,10 +311,6 @@ export interface Electron { ) => Promise; // - FS legacy - saveStreamToDisk: ( - path: string, - fileStream: ReadableStream, - ) => Promise; isFolder: (dirPath: string) => Promise; // - Upload From 83d2644bf41eb97a3f134d2446f57b1ec618f66f Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 15 Apr 2024 19:43:30 +0530 Subject: [PATCH 49/84] Fix double slashing --- desktop/src/main/stream.ts | 4 ++-- web/apps/photos/src/utils/native-stream.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/desktop/src/main/stream.ts b/desktop/src/main/stream.ts index 5f9ce55732..f1ebe698e7 100644 --- a/desktop/src/main/stream.ts +++ b/desktop/src/main/stream.ts @@ -31,8 +31,8 @@ export const registerStreamProtocol = () => { const url = request.url; const { host, pathname } = new URL(url); switch (host) { - /* stream://write//path/to/file */ - /* -host/pathname----- */ + /* stream://write/path/to/file */ + /* host-pathname----- */ case "write": try { await writeStream(pathname, request.body); diff --git a/web/apps/photos/src/utils/native-stream.ts b/web/apps/photos/src/utils/native-stream.ts index b7617e4afa..809aa9e209 100644 --- a/web/apps/photos/src/utils/native-stream.ts +++ b/web/apps/photos/src/utils/native-stream.ts @@ -25,7 +25,7 @@ export const writeStream = async (path: string, stream: ReadableStream) => { // In another twist, the TypeScript libdom.d.ts does not include the // "duplex" parameter, so we need to cast to get TypeScript to let this code // through. e.g. see https://github.com/node-fetch/node-fetch/issues/1769 - const req = new Request(`stream://write/${path}`, { + const req = new Request(`stream://write${path}`, { // GET can't have a body method: "POST", body: stream, From f2e352c34454e6d0721d563b32a03eed74f1b42e Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 15 Apr 2024 19:50:56 +0530 Subject: [PATCH 50/84] Handle spaces --- desktop/src/main/stream.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/desktop/src/main/stream.ts b/desktop/src/main/stream.ts index f1ebe698e7..8ddb80dc6a 100644 --- a/desktop/src/main/stream.ts +++ b/desktop/src/main/stream.ts @@ -30,12 +30,14 @@ export const registerStreamProtocol = () => { protocol.handle("stream", async (request: Request) => { const url = request.url; const { host, pathname } = new URL(url); + // Convert e.g. "%20" to spaces. + const path = decodeURIComponent(pathname); switch (host) { /* stream://write/path/to/file */ /* host-pathname----- */ case "write": try { - await writeStream(pathname, request.body); + await writeStream(path, request.body); return new Response("", { status: 200 }); } catch (e) { log.error(`Failed to write stream for ${url}`, e); From 09c07e58e6ccadf71bae96aee66a574886501d7a Mon Sep 17 00:00:00 2001 From: daviddeepan Date: Mon, 15 Apr 2024 19:54:33 +0530 Subject: [PATCH 51/84] search-input runtime-error fix --- .../src/components/Search/SearchBar/searchInput/index.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/web/apps/photos/src/components/Search/SearchBar/searchInput/index.tsx b/web/apps/photos/src/components/Search/SearchBar/searchInput/index.tsx index ca52b9cadb..4e9552a1df 100644 --- a/web/apps/photos/src/components/Search/SearchBar/searchInput/index.tsx +++ b/web/apps/photos/src/components/Search/SearchBar/searchInput/index.tsx @@ -56,8 +56,11 @@ export default function SearchInput(props: Iprops) { const [value, setValue] = useState(null); const appContext = useContext(AppContext); const handleChange = (value: SearchOption) => { - setValue(value); - setQuery(value.label); + if (value) { + setValue(value); + setQuery(value.label); + } + blur(); }; const handleInputChange = (value: string, actionMeta: InputActionMeta) => { From 8d76966d999a6a75c9a8f3125e5b9a86b1e7d803 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 15 Apr 2024 21:14:31 +0530 Subject: [PATCH 52/84] Upgrade Electron and other dependencies This was primarily for getting the latest Electron, but I ran `yarn upgrade-interactive` and upgraded the other non-breaking deps (mostly dev) too. Reason for wanting electron is to try and see if this backport fixes the issue with our streams not getting faithfully written: https://github.com/electron/electron/pull/41052 In some ad-hoc and quick testing, I noticed that the new `writeStream` we've implemented works fine for files up to 128 K, presumably some chunk size, but then begins to diverge. Sounds similar (but not exactly the same) as this issue: https://github.com/electron/electron/issues/39658 Unfortunately, this didn't fix the issue we're facing, so our case is perhaps different. --- desktop/package.json | 4 +- desktop/yarn.lock | 192 ++++++++++++++++++++++--------------------- 2 files changed, 102 insertions(+), 94 deletions(-) diff --git a/desktop/package.json b/desktop/package.json index 032953d8d0..69d54f75be 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -44,8 +44,8 @@ "electron-builder-notarize": "^1.5", "eslint": "^8", "prettier": "^3", - "prettier-plugin-organize-imports": "^3.2", - "prettier-plugin-packagejson": "^2.4", + "prettier-plugin-organize-imports": "^3", + "prettier-plugin-packagejson": "^2", "shx": "^0.3", "typescript": "^5" }, diff --git a/desktop/yarn.lock b/desktop/yarn.lock index a4cc12cfe4..a5b86f1eb3 100644 --- a/desktop/yarn.lock +++ b/desktop/yarn.lock @@ -125,7 +125,7 @@ dependencies: eslint-visitor-keys "^3.3.0" -"@eslint-community/regexpp@^4.5.1", "@eslint-community/regexpp@^4.6.1": +"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.6.1": version "4.10.0" resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== @@ -285,7 +285,7 @@ resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz#b979ebad3919799c979b17c72621c0bc0a31c6c4" integrity sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA== -"@types/json-schema@^7.0.12": +"@types/json-schema@^7.0.15": version "7.0.15" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== @@ -303,9 +303,9 @@ integrity sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g== "@types/node@*", "@types/node@^20.9.0": - version "20.11.30" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.30.tgz#9c33467fc23167a347e73834f788f4b9f399d66f" - integrity sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw== + version "20.12.7" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.7.tgz#04080362fa3dd6c5822061aa3124f5c152cff384" + integrity sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg== dependencies: undici-types "~5.26.4" @@ -334,7 +334,7 @@ dependencies: "@types/node" "*" -"@types/semver@^7.5.0": +"@types/semver@^7.5.8": version "7.5.8" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== @@ -352,90 +352,90 @@ "@types/node" "*" "@typescript-eslint/eslint-plugin@^7": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.4.0.tgz#de61c3083842fc6ac889d2fc83c9a96b55ab8328" - integrity sha512-yHMQ/oFaM7HZdVrVm/M2WHaNPgyuJH4WelkSVEWSSsir34kxW2kDJCxlXRhhGWEsMN0WAW/vLpKfKVcm8k+MPw== + version "7.6.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.6.0.tgz#1f5df5cda490a0bcb6fbdd3382e19f1241024242" + integrity sha512-gKmTNwZnblUdnTIJu3e9kmeRRzV2j1a/LUO27KNNAnIC5zjy1aSvXSRp4rVNlmAoHlQ7HzX42NbKpcSr4jF80A== dependencies: - "@eslint-community/regexpp" "^4.5.1" - "@typescript-eslint/scope-manager" "7.4.0" - "@typescript-eslint/type-utils" "7.4.0" - "@typescript-eslint/utils" "7.4.0" - "@typescript-eslint/visitor-keys" "7.4.0" + "@eslint-community/regexpp" "^4.10.0" + "@typescript-eslint/scope-manager" "7.6.0" + "@typescript-eslint/type-utils" "7.6.0" + "@typescript-eslint/utils" "7.6.0" + "@typescript-eslint/visitor-keys" "7.6.0" debug "^4.3.4" graphemer "^1.4.0" - ignore "^5.2.4" + ignore "^5.3.1" natural-compare "^1.4.0" - semver "^7.5.4" - ts-api-utils "^1.0.1" + semver "^7.6.0" + ts-api-utils "^1.3.0" "@typescript-eslint/parser@^7": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.4.0.tgz#540f4321de1e52b886c0fa68628af1459954c1f1" - integrity sha512-ZvKHxHLusweEUVwrGRXXUVzFgnWhigo4JurEj0dGF1tbcGh6buL+ejDdjxOQxv6ytcY1uhun1p2sm8iWStlgLQ== + version "7.6.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.6.0.tgz#0aca5de3045d68b36e88903d15addaf13d040a95" + integrity sha512-usPMPHcwX3ZoPWnBnhhorc14NJw9J4HpSXQX4urF2TPKG0au0XhJoZyX62fmvdHONUkmyUe74Hzm1//XA+BoYg== dependencies: - "@typescript-eslint/scope-manager" "7.4.0" - "@typescript-eslint/types" "7.4.0" - "@typescript-eslint/typescript-estree" "7.4.0" - "@typescript-eslint/visitor-keys" "7.4.0" + "@typescript-eslint/scope-manager" "7.6.0" + "@typescript-eslint/types" "7.6.0" + "@typescript-eslint/typescript-estree" "7.6.0" + "@typescript-eslint/visitor-keys" "7.6.0" debug "^4.3.4" -"@typescript-eslint/scope-manager@7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.4.0.tgz#acfc69261f10ece7bf7ece1734f1713392c3655f" - integrity sha512-68VqENG5HK27ypafqLVs8qO+RkNc7TezCduYrx8YJpXq2QGZ30vmNZGJJJC48+MVn4G2dCV8m5ZTVnzRexTVtw== +"@typescript-eslint/scope-manager@7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.6.0.tgz#1e9972f654210bd7500b31feadb61a233f5b5e9d" + integrity sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w== dependencies: - "@typescript-eslint/types" "7.4.0" - "@typescript-eslint/visitor-keys" "7.4.0" + "@typescript-eslint/types" "7.6.0" + "@typescript-eslint/visitor-keys" "7.6.0" -"@typescript-eslint/type-utils@7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.4.0.tgz#cfcaab21bcca441c57da5d3a1153555e39028cbd" - integrity sha512-247ETeHgr9WTRMqHbbQdzwzhuyaJ8dPTuyuUEMANqzMRB1rj/9qFIuIXK7l0FX9i9FXbHeBQl/4uz6mYuCE7Aw== +"@typescript-eslint/type-utils@7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.6.0.tgz#644f75075f379827d25fe0713e252ccd4e4a428c" + integrity sha512-NxAfqAPNLG6LTmy7uZgpK8KcuiS2NZD/HlThPXQRGwz6u7MDBWRVliEEl1Gj6U7++kVJTpehkhZzCJLMK66Scw== dependencies: - "@typescript-eslint/typescript-estree" "7.4.0" - "@typescript-eslint/utils" "7.4.0" + "@typescript-eslint/typescript-estree" "7.6.0" + "@typescript-eslint/utils" "7.6.0" debug "^4.3.4" - ts-api-utils "^1.0.1" + ts-api-utils "^1.3.0" -"@typescript-eslint/types@7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.4.0.tgz#ee9dafa75c99eaee49de6dcc9348b45d354419b6" - integrity sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw== +"@typescript-eslint/types@7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.6.0.tgz#53dba7c30c87e5f10a731054266dd905f1fbae38" + integrity sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ== -"@typescript-eslint/typescript-estree@7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.4.0.tgz#12dbcb4624d952f72c10a9f4431284fca24624f4" - integrity sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg== +"@typescript-eslint/typescript-estree@7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.6.0.tgz#112a3775563799fd3f011890ac8322f80830ac17" + integrity sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw== dependencies: - "@typescript-eslint/types" "7.4.0" - "@typescript-eslint/visitor-keys" "7.4.0" + "@typescript-eslint/types" "7.6.0" + "@typescript-eslint/visitor-keys" "7.6.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" - minimatch "9.0.3" - semver "^7.5.4" - ts-api-utils "^1.0.1" + minimatch "^9.0.4" + semver "^7.6.0" + ts-api-utils "^1.3.0" -"@typescript-eslint/utils@7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.4.0.tgz#d889a0630cab88bddedaf7c845c64a00576257bd" - integrity sha512-NQt9QLM4Tt8qrlBVY9lkMYzfYtNz8/6qwZg8pI3cMGlPnj6mOpRxxAm7BMJN9K0AiY+1BwJ5lVC650YJqYOuNg== +"@typescript-eslint/utils@7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.6.0.tgz#e400d782280b6f724c8a1204269d984c79202282" + integrity sha512-x54gaSsRRI+Nwz59TXpCsr6harB98qjXYzsRxGqvA5Ue3kQH+FxS7FYU81g/omn22ML2pZJkisy6Q+ElK8pBCA== dependencies: "@eslint-community/eslint-utils" "^4.4.0" - "@types/json-schema" "^7.0.12" - "@types/semver" "^7.5.0" - "@typescript-eslint/scope-manager" "7.4.0" - "@typescript-eslint/types" "7.4.0" - "@typescript-eslint/typescript-estree" "7.4.0" - semver "^7.5.4" + "@types/json-schema" "^7.0.15" + "@types/semver" "^7.5.8" + "@typescript-eslint/scope-manager" "7.6.0" + "@typescript-eslint/types" "7.6.0" + "@typescript-eslint/typescript-estree" "7.6.0" + semver "^7.6.0" -"@typescript-eslint/visitor-keys@7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.4.0.tgz#0c8ff2c1f8a6fe8d7d1a57ebbd4a638e86a60a94" - integrity sha512-0zkC7YM0iX5Y41homUUeW1CHtZR01K3ybjM1l6QczoMuay0XKtrb93kv95AxUGwdjGr64nNqnOCwmEl616N8CA== +"@typescript-eslint/visitor-keys@7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz#d1ce13145844379021e1f9bd102c1d78946f4e76" + integrity sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw== dependencies: - "@typescript-eslint/types" "7.4.0" - eslint-visitor-keys "^3.4.1" + "@typescript-eslint/types" "7.6.0" + eslint-visitor-keys "^3.4.3" "@ungap/structured-clone@^1.2.0": version "1.2.0" @@ -1140,9 +1140,9 @@ ejs@^3.1.8: jake "^10.8.5" electron-builder-notarize@^1.5: - version "1.5.1" - resolved "https://registry.yarnpkg.com/electron-builder-notarize/-/electron-builder-notarize-1.5.1.tgz#e00b868a67ef20a77f00017606626f24fdbdc445" - integrity sha512-xS7s9gE+1AcJIuJ4DU/LqCrmRypE1zOR/6b66egKzgP/UVh9YSa7rINos34gF/KcueNDQU39HcXcCEKiEI5wPQ== + version "1.5.2" + resolved "https://registry.yarnpkg.com/electron-builder-notarize/-/electron-builder-notarize-1.5.2.tgz#540185b57a336fc6eec01bfe092a3b4764459255" + integrity sha512-vo6RGgIFYxMk2yp59N4NsvmAYfB7ncYi6gV9Fcq2TVKxEn2tPXrSjIKB2e/pu+5iXIY6BHNZNXa75F3DHgOOLA== dependencies: dotenv "^8.2.0" electron-notarize "^1.1.1" @@ -1215,9 +1215,9 @@ electron-updater@^6.1: tiny-typed-emitter "^2.1.0" electron@^29: - version "29.1.5" - resolved "https://registry.yarnpkg.com/electron/-/electron-29.1.5.tgz#b745b4d201c1ac9f84d6aa034126288dde34d5a1" - integrity sha512-1uWGRw/ffA62lcrklxGUgVxVtOHojsg/nwsYr+/F9cVjipZJn8iPv/ABGIIexhmUqWcho8BqfTJ4osCBa29gBg== + version "29.3.0" + resolved "https://registry.yarnpkg.com/electron/-/electron-29.3.0.tgz#8e65cb08e9c0952c66d3196e1b5c811c43b8c5b0" + integrity sha512-ZxFKm0/v48GSoBuO3DdnMlCYXefEUKUHLMsKxyXY4nZGgzbBKpF/X8haZa2paNj23CLfsCKBOtfc2vsEQiOOsA== dependencies: "@electron/get" "^2.0.0" "@types/node" "^20.9.0" @@ -1835,7 +1835,7 @@ ieee754@^1.1.13: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== -ignore@^5.2.0, ignore@^5.2.4: +ignore@^5.2.0, ignore@^5.2.4, ignore@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== @@ -2190,13 +2190,6 @@ mimic-response@^3.1.0: resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== -minimatch@9.0.3, minimatch@^9.0.1: - version "9.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" - integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== - dependencies: - brace-expansion "^2.0.1" - minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -2211,6 +2204,20 @@ minimatch@^5.0.1, minimatch@^5.1.1: dependencies: brace-expansion "^2.0.1" +minimatch@^9.0.1: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^9.0.4: + version "9.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51" + integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw== + dependencies: + brace-expansion "^2.0.1" + minimist@^1.2.3, minimist@^1.2.6: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" @@ -2482,17 +2489,17 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -prettier-plugin-organize-imports@^3.2: +prettier-plugin-organize-imports@^3: version "3.2.4" resolved "https://registry.yarnpkg.com/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-3.2.4.tgz#77967f69d335e9c8e6e5d224074609309c62845e" integrity sha512-6m8WBhIp0dfwu0SkgfOxJqh+HpdyfqSSLfKKRZSFbDuEQXDDndb8fTpRWkUrX/uBenkex3MgnVk0J3b3Y5byog== -prettier-plugin-packagejson@^2.4: - version "2.4.12" - resolved "https://registry.yarnpkg.com/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.4.12.tgz#eeb917dad83ae42d0caccc9f26d3728b5c4f2434" - integrity sha512-hifuuOgw5rHHTdouw9VrhT8+Nd7UwxtL1qco8dUfd4XUFQL6ia3xyjSxhPQTsGnSYFraTWy5Omb+MZm/OWDTpQ== +prettier-plugin-packagejson@^2: + version "2.5.0" + resolved "https://registry.yarnpkg.com/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.5.0.tgz#23d2cb8b1f7840702d35e3a5078e564ea0bc63e0" + integrity sha512-6XkH3rpin5QEQodBSVNg+rBo4r91g/1mCaRwS1YGdQJZ6jwqrg2UchBsIG9tpS1yK1kNBvOt84OILsX8uHzBGg== dependencies: - sort-package-json "2.8.0" + sort-package-json "2.10.0" synckit "0.9.0" prettier@^3: @@ -2711,7 +2718,7 @@ semver@^6.2.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.3.2, semver@^7.3.5, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4: +semver@^7.3.2, semver@^7.3.5, semver@^7.3.8, semver@^7.5.3, semver@^7.6.0: version "7.6.0" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== @@ -2800,10 +2807,10 @@ sort-object-keys@^1.1.3: resolved "https://registry.yarnpkg.com/sort-object-keys/-/sort-object-keys-1.1.3.tgz#bff833fe85cab147b34742e45863453c1e190b45" integrity sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg== -sort-package-json@2.8.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/sort-package-json/-/sort-package-json-2.8.0.tgz#6a46439ad0fef77f091e678e103f03ecbea575c8" - integrity sha512-PxeNg93bTJWmDGnu0HADDucoxfFiKkIr73Kv85EBThlI1YQPdc0XovBgg2llD0iABZbu2SlKo8ntGmOP9wOj/g== +sort-package-json@2.10.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/sort-package-json/-/sort-package-json-2.10.0.tgz#6be07424bf3b7db9fbb1bdd69e7945f301026d8a" + integrity sha512-MYecfvObMwJjjJskhxYfuOADkXp1ZMMnCFC8yhp+9HDsk7HhR336hd7eiBs96lTXfiqmUNI+WQCeCMRBhl251g== dependencies: detect-indent "^7.0.1" detect-newline "^4.0.0" @@ -2811,6 +2818,7 @@ sort-package-json@2.8.0: git-hooks-list "^3.0.0" globby "^13.1.2" is-plain-obj "^4.1.0" + semver "^7.6.0" sort-object-keys "^1.1.3" source-map-support@^0.5.19: @@ -3018,7 +3026,7 @@ truncate-utf8-bytes@^1.0.0: dependencies: utf8-byte-length "^1.0.1" -ts-api-utils@^1.0.1: +ts-api-utils@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== From a5be903abe229616887e84c8af82530e3d303e30 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 15 Apr 2024 21:37:38 +0530 Subject: [PATCH 53/84] Try writing the stream manually (same result) --- desktop/src/main/stream.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/desktop/src/main/stream.ts b/desktop/src/main/stream.ts index 8ddb80dc6a..2d0eaa62c0 100644 --- a/desktop/src/main/stream.ts +++ b/desktop/src/main/stream.ts @@ -37,7 +37,16 @@ export const registerStreamProtocol = () => { /* host-pathname----- */ case "write": try { - await writeStream(path, request.body); + // await writeStream(path, request.body); + console.log("starting stream"); + let c = 0; + for await (const p of request.body as any) { + if (c == 327680) console.log(p); + fs.appendFile(path, p); + c += p.length; + } + console.log("ending stream"); + return new Response("", { status: 200 }); } catch (e) { log.error(`Failed to write stream for ${url}`, e); From 587f72168308ae59e2a7244ee1db815719f9c88f Mon Sep 17 00:00:00 2001 From: Prateek Sunal Date: Mon, 15 Apr 2024 21:43:30 +0530 Subject: [PATCH 54/84] fix: revert old --- mobile/android/app/build.gradle | 10 ---------- mobile/pubspec.yaml | 5 ++--- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/mobile/android/app/build.gradle b/mobile/android/app/build.gradle index 801efe6ebc..01ec11ff8a 100644 --- a/mobile/android/app/build.gradle +++ b/mobile/android/app/build.gradle @@ -11,11 +11,6 @@ if (localPropertiesFile.exists()) { } } -/*def flutterRoot = localProperties.getProperty('flutter.sdk') -if (flutterRoot == null) { - throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") -}*/ - def flutterVersionCode = localProperties.getProperty('flutter.versionCode') if (flutterVersionCode == null) { flutterVersionCode = '1' @@ -26,11 +21,6 @@ if (flutterVersionName == null) { flutterVersionName = '1.0' } -//apply plugin: 'com.android.application' -//apply plugin: 'kotlin-android' -//apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" - - def keystoreProperties = new Properties() def keystorePropertiesFile = rootProject.file('key.properties') if (keystorePropertiesFile.exists()) { diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index f52cfe555e..9f26ef1e11 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -176,9 +176,8 @@ dependencies: dependency_overrides: connectivity_plus: ^4.0.0 - - #Remove this after upgrading to flutter v3.19x - #Build fails when resolving to latest version of ffi on flutter v3.16.x + # Remove this after removing dependency from flutter_sodium. + # Newer flutter packages depends on ffi > 2.0.0 while flutter_sodium depends on ffi < 2.0.0 ffi: 2.1.0 video_player: git: From 2577cfe2f10e523a63a7efb3a8824acce7b9c750 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 15 Apr 2024 21:43:38 +0530 Subject: [PATCH 55/84] Replace cast with @ts-expect-error --- web/apps/photos/src/utils/native-stream.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/web/apps/photos/src/utils/native-stream.ts b/web/apps/photos/src/utils/native-stream.ts index 809aa9e209..65db237b30 100644 --- a/web/apps/photos/src/utils/native-stream.ts +++ b/web/apps/photos/src/utils/native-stream.ts @@ -21,16 +21,15 @@ export const writeStream = async (path: string, stream: ReadableStream) => { // only within our desktop (Electron) app, Chromium, don't support 'full' // duplex mode (i.e. streaming both the request and the response). // https://developer.chrome.com/docs/capabilities/web-apis/fetch-streaming-requests - // - // In another twist, the TypeScript libdom.d.ts does not include the - // "duplex" parameter, so we need to cast to get TypeScript to let this code - // through. e.g. see https://github.com/node-fetch/node-fetch/issues/1769 const req = new Request(`stream://write${path}`, { // GET can't have a body method: "POST", body: stream, + // @ts-expect-error TypeScript's libdom.d.ts does not include the + // "duplex" parameter, e.g. see + // https://github.com/node-fetch/node-fetch/issues/1769. duplex: "half", - } as unknown as RequestInit); + }); const res = await fetch(req); if (!res.ok) throw new Error( From 311d23873efc1aeeab0a9042337b8422d2b0ddac Mon Sep 17 00:00:00 2001 From: Prateek Sunal Date: Mon, 15 Apr 2024 21:44:49 +0530 Subject: [PATCH 56/84] chore: bump version --- mobile/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index b095b90c46..f1575bdf8b 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -12,7 +12,7 @@ description: ente photos application # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 0.8.80+600 +version: 0.8.81+601 publish_to: none environment: From 0f4624e82968aebe43bd8a2108192cccf6d77f64 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Tue, 16 Apr 2024 01:37:39 +0000 Subject: [PATCH 57/84] New Crowdin translations by GitHub Action --- .../next/locales/de-DE/translation.json | 194 +++++++++--------- .../next/locales/sv-SE/translation.json | 4 +- 2 files changed, 99 insertions(+), 99 deletions(-) diff --git a/web/packages/next/locales/de-DE/translation.json b/web/packages/next/locales/de-DE/translation.json index 7a7a2a3d9c..38b877fd43 100644 --- a/web/packages/next/locales/de-DE/translation.json +++ b/web/packages/next/locales/de-DE/translation.json @@ -2,8 +2,8 @@ "HERO_SLIDE_1_TITLE": "
Private Sicherungen
für deine Erinnerungen
", "HERO_SLIDE_1": "Standardmäßig Ende-zu-Ende verschlüsselt", "HERO_SLIDE_2_TITLE": "
Sicher gespeichert
in einem Luftschutzbunker
", - "HERO_SLIDE_2": "Entwickelt um zu bewahren", - "HERO_SLIDE_3_TITLE": "
Verfügbar
überall
", + "HERO_SLIDE_2": "Entwickelt um zu überleben", + "HERO_SLIDE_3_TITLE": "
Überall
verfügbar
", "HERO_SLIDE_3": "Android, iOS, Web, Desktop", "LOGIN": "Anmelden", "SIGN_UP": "Registrieren", @@ -168,7 +168,7 @@ "UPDATE_PAYMENT_METHOD": "Zahlungsmethode aktualisieren", "MONTHLY": "Monatlich", "YEARLY": "Jährlich", - "update_subscription_title": "", + "update_subscription_title": "Tarifänderung bestätigen", "UPDATE_SUBSCRIPTION_MESSAGE": "Sind Sie sicher, dass Sie Ihren Tarif ändern möchten?", "UPDATE_SUBSCRIPTION": "Plan ändern", "CANCEL_SUBSCRIPTION": "Abonnement kündigen", @@ -278,15 +278,15 @@ "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "Ihr Browser oder ein Addon blockiert Ente vor der Speicherung von Daten im lokalen Speicher. Bitte versuchen Sie, den Browser-Modus zu wechseln und die Seite neu zu laden.", "SEND_OTT": "OTP senden", "EMAIl_ALREADY_OWNED": "Diese E-Mail wird bereits verwendet", - "ETAGS_BLOCKED": "", - "LIVE_PHOTOS_DETECTED": "", + "ETAGS_BLOCKED": "

Die folgenden Dateien konnten aufgrund deiner Browser-Konfiguration nicht hochgeladen werden.

Bitte deaktiviere alle Add-ons, die Ente daran hindern könnten, eTags zum Hochladen großer Dateien zu verwenden oder verwende unsere Desktop-App für ein zuverlässigeres Import-Erlebnis.

", + "LIVE_PHOTOS_DETECTED": "Die Foto- und Videodateien deiner Live-Fotos wurden in einer einzigen Datei zusammengeführt", "RETRY_FAILED": "Fehlgeschlagene Uploads erneut probieren", "FAILED_UPLOADS": "Fehlgeschlagene Uploads ", "SKIPPED_FILES": "Ignorierte Uploads", "THUMBNAIL_GENERATION_FAILED_UPLOADS": "Das Vorschaubild konnte nicht erzeugt werden", "UNSUPPORTED_FILES": "Nicht unterstützte Dateien", "SUCCESSFUL_UPLOADS": "Erfolgreiche Uploads", - "SKIPPED_INFO": "", + "SKIPPED_INFO": "Diese wurden übersprungen, da es Dateien mit gleichen Namen im selben Album gibt", "UNSUPPORTED_INFO": "Ente unterstützt diese Dateiformate noch nicht", "BLOCKED_UPLOADS": "Blockierte Uploads", "INPROGRESS_METADATA_EXTRACTION": "In Bearbeitung", @@ -315,20 +315,20 @@ "REMOVE_FROM_COLLECTION": "Aus Album entfernen", "TRASH": "Papierkorb", "MOVE_TO_TRASH": "In Papierkorb verschieben", - "TRASH_FILES_MESSAGE": "", - "TRASH_FILE_MESSAGE": "", + "TRASH_FILES_MESSAGE": "Ausgewählte Dateien werden aus allen Alben entfernt und in den Papierkorb verschoben.", + "TRASH_FILE_MESSAGE": "Die Datei wird aus allen Alben entfernt und in den Papierkorb verschoben.", "DELETE_PERMANENTLY": "Dauerhaft löschen", "RESTORE": "Wiederherstellen", "RESTORE_TO_COLLECTION": "In Album wiederherstellen", "EMPTY_TRASH": "Papierkorb leeren", "EMPTY_TRASH_TITLE": "Papierkorb leeren?", - "EMPTY_TRASH_MESSAGE": "", + "EMPTY_TRASH_MESSAGE": "Diese Dateien werden dauerhaft aus Ihrem Ente-Konto gelöscht.", "LEAVE_SHARED_ALBUM": "Ja, verlassen", "LEAVE_ALBUM": "Album verlassen", "LEAVE_SHARED_ALBUM_TITLE": "Geteiltes Album verlassen?", - "LEAVE_SHARED_ALBUM_MESSAGE": "", + "LEAVE_SHARED_ALBUM_MESSAGE": "Du wirst das Album verlassen und es wird nicht mehr für dich sichtbar sein.", "NOT_FILE_OWNER": "Dateien in einem freigegebenen Album können nicht gelöscht werden", - "CONFIRM_SELF_REMOVE_MESSAGE": "", + "CONFIRM_SELF_REMOVE_MESSAGE": "Ausgewählte Elemente werden aus diesem Album entfernt. Elemente, die sich nur in diesem Album befinden, werden nach Unkategorisiert verschoben.", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "Einige der Elemente, die du entfernst, wurden von anderen Nutzern hinzugefügt und du wirst den Zugriff auf sie verlieren.", "SORT_BY_CREATION_TIME_ASCENDING": "Ältestem", "SORT_BY_UPDATION_TIME_DESCENDING": "Zuletzt aktualisiert", @@ -337,8 +337,8 @@ "FIX_CREATION_TIME_IN_PROGRESS": "Zeit wird repariert", "CREATION_TIME_UPDATED": "Datei-Zeit aktualisiert", "UPDATE_CREATION_TIME_NOT_STARTED": "Wählen Sie die Option, die Sie verwenden möchten", - "UPDATE_CREATION_TIME_COMPLETED": "", - "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", + "UPDATE_CREATION_TIME_COMPLETED": "Alle Dateien erfolgreich aktualisiert", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "Aktualisierung der Dateizeit für einige Dateien fehlgeschlagen, bitte versuche es erneut", "CAPTION_CHARACTER_LIMIT": "Maximal 5000 Zeichen", "DATE_TIME_ORIGINAL": "", "DATE_TIME_DIGITIZED": "", @@ -358,10 +358,10 @@ "participants_one": "1 Teilnehmer", "participants_other": "{{count, number}} Teilnehmer", "ADD_VIEWERS": "Betrachter hinzufügen", - "CHANGE_PERMISSIONS_TO_VIEWER": "", - "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", + "CHANGE_PERMISSIONS_TO_VIEWER": "

{{selectedEmail}} wird nicht in der Lage sein, weitere Fotos zum Album

hinzuzufügen. {{selectedEmail}} wird weiterhin die eigenen Fotos aus dem Album entfernen können

", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "{{selectedEmail}} wird Fotos zum Album hinzufügen können", "CONVERT_TO_VIEWER": "Ja, zu \"Beobachter\" ändern", - "CONVERT_TO_COLLABORATOR": "", + "CONVERT_TO_COLLABORATOR": "Ja, in Kollaborateur umwandeln", "CHANGE_PERMISSION": "Berechtigung ändern?", "REMOVE_PARTICIPANT": "Entfernen?", "CONFIRM_REMOVE": "Ja, entfernen", @@ -408,11 +408,11 @@ "STOP_ALL_UPLOADS_MESSAGE": "", "STOP_UPLOADS_HEADER": "Hochladen stoppen?", "YES_STOP_UPLOADS": "Ja, Hochladen stoppen", - "STOP_DOWNLOADS_HEADER": "", - "YES_STOP_DOWNLOADS": "", - "STOP_ALL_DOWNLOADS_MESSAGE": "", + "STOP_DOWNLOADS_HEADER": "Downloads anhalten?", + "YES_STOP_DOWNLOADS": "Ja, Downloads anhalten", + "STOP_ALL_DOWNLOADS_MESSAGE": "Bist du dir sicher, dass du alle laufenden Downloads anhalten möchtest?", "albums_one": "1 Album", - "albums_other": "", + "albums_other": "{{count, number}} Alben", "ALL_ALBUMS": "Alle Alben", "ALBUMS": "Alben", "ALL_HIDDEN_ALBUMS": "", @@ -424,7 +424,7 @@ "COPIED": "Kopiert", "WATCH_FOLDERS": "", "UPGRADE_NOW": "Jetzt upgraden", - "RENEW_NOW": "", + "RENEW_NOW": "Jetzt erneuern", "STORAGE": "Speicher", "USED": "verwendet", "YOU": "Sie", @@ -432,10 +432,10 @@ "FREE": "frei", "OF": "von", "WATCHED_FOLDERS": "", - "NO_FOLDERS_ADDED": "", + "NO_FOLDERS_ADDED": "Noch keine Ordner hinzugefügt!", "FOLDERS_AUTOMATICALLY_MONITORED": "", "UPLOAD_NEW_FILES_TO_ENTE": "", - "REMOVE_DELETED_FILES_FROM_ENTE": "", + "REMOVE_DELETED_FILES_FROM_ENTE": "Gelöschte Dateien aus Ente entfernen", "ADD_FOLDER": "Ordner hinzufügen", "STOP_WATCHING": "", "STOP_WATCHING_FOLDER": "", @@ -455,48 +455,48 @@ "CURRENT_USAGE": "Aktuelle Nutzung ist {{usage}}", "WEAK_DEVICE": "", "DRAG_AND_DROP_HINT": "", - "CONFIRM_ACCOUNT_DELETION_MESSAGE": "", + "CONFIRM_ACCOUNT_DELETION_MESSAGE": "Ihre hochgeladenen Daten werden zur Löschung vorgemerkt, und Ihr Konto wird endgültig gelöscht.

Dieser Vorgang kann nicht rückgängig gemacht werden.", "AUTHENTICATE": "Authentifizieren", "UPLOADED_TO_SINGLE_COLLECTION": "", "UPLOADED_TO_SEPARATE_COLLECTIONS": "", "NEVERMIND": "Egal", "UPDATE_AVAILABLE": "Neue Version verfügbar", - "UPDATE_INSTALLABLE_MESSAGE": "", + "UPDATE_INSTALLABLE_MESSAGE": "Eine neue Version von Ente ist für die Installation bereit.", "INSTALL_NOW": "Jetzt installieren", "INSTALL_ON_NEXT_LAUNCH": "Beim nächsten Start installieren", - "UPDATE_AVAILABLE_MESSAGE": "", - "DOWNLOAD_AND_INSTALL": "", + "UPDATE_AVAILABLE_MESSAGE": "Eine neue Version von Ente wurde veröffentlicht, aber sie kann nicht automatisch heruntergeladen und installiert werden.", + "DOWNLOAD_AND_INSTALL": "Herunterladen und installieren", "IGNORE_THIS_VERSION": "Diese Version ignorieren", "TODAY": "Heute", "YESTERDAY": "Gestern", "NAME_PLACEHOLDER": "Name...", - "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "Alben können nicht aus Datei/Ordnermix erstellt werden", "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "", - "CHOSE_THEME": "", - "ML_SEARCH": "", + "CHOSE_THEME": "Design auswählen", + "ML_SEARCH": "Gesichtserkennung", "ENABLE_ML_SEARCH_DESCRIPTION": "", - "ML_MORE_DETAILS": "", - "ENABLE_FACE_SEARCH": "", - "ENABLE_FACE_SEARCH_TITLE": "", - "ENABLE_FACE_SEARCH_DESCRIPTION": "", + "ML_MORE_DETAILS": "Weitere Details", + "ENABLE_FACE_SEARCH": "Gesichtserkennung aktivieren", + "ENABLE_FACE_SEARCH_TITLE": "Gesichtserkennung aktivieren?", + "ENABLE_FACE_SEARCH_DESCRIPTION": "

Wenn du die Gesichtserkennung aktivierst, wird Ente Gesichtsgeometrie aus deinen Fotos extrahieren. Dies wird auf deinem Gerät geschehen, und alle erzeugten biometrischen Daten werden Ende-zu-verschlüsselt.

Bitte klicke hier für weitere Informationen über diese Funktion in unserer Datenschutzerklärung

", "DISABLE_BETA": "Beta deaktivieren", - "DISABLE_FACE_SEARCH": "", - "DISABLE_FACE_SEARCH_TITLE": "", + "DISABLE_FACE_SEARCH": "Gesichtserkennung deaktivieren", + "DISABLE_FACE_SEARCH_TITLE": "Gesichtserkennung deaktivieren?", "DISABLE_FACE_SEARCH_DESCRIPTION": "", "ADVANCED": "Erweitert", - "FACE_SEARCH_CONFIRMATION": "", - "LABS": "", + "FACE_SEARCH_CONFIRMATION": "Ich verstehe und möchte Ente erlauben, Gesichtsgeometrie zu verarbeiten", + "LABS": "Experimente", "YOURS": "", "PASSPHRASE_STRENGTH_WEAK": "Passwortstärke: Schwach", - "PASSPHRASE_STRENGTH_MODERATE": "", + "PASSPHRASE_STRENGTH_MODERATE": "Passwortstärke: Moderat", "PASSPHRASE_STRENGTH_STRONG": "Passwortstärke: Stark", "PREFERENCES": "Einstellungen", "LANGUAGE": "Sprache", - "EXPORT_DIRECTORY_DOES_NOT_EXIST": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST": "Ungültiges Exportverzeichnis", "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "", - "SUBSCRIPTION_VERIFICATION_ERROR": "", + "SUBSCRIPTION_VERIFICATION_ERROR": "Verifizierung des Abonnements fehlgeschlagen", "STORAGE_UNITS": { - "B": "", + "B": "B", "KB": "KB", "MB": "MB", "GB": "GB", @@ -520,8 +520,8 @@ "PUBLIC_COLLECT_SUBTEXT": "", "STOP_EXPORT": "Stop", "EXPORT_PROGRESS": "", - "MIGRATING_EXPORT": "", - "RENAMING_COLLECTION_FOLDERS": "", + "MIGRATING_EXPORT": "Vorbereiten...", + "RENAMING_COLLECTION_FOLDERS": "Albumordner umbenennen...", "TRASHING_DELETED_FILES": "", "TRASHING_DELETED_COLLECTIONS": "", "CONTINUOUS_EXPORT": "", @@ -536,12 +536,12 @@ "NOT_LISTED": "" }, "DELETE_ACCOUNT_FEEDBACK_LABEL": "", - "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "", - "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "", + "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "Feedback", + "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "Ja, ich möchte dieses Konto und alle enthaltenen Daten endgültig und unwiderruflich löschen", "CONFIRM_DELETE_ACCOUNT": "Kontolöschung bestätigen", "FEEDBACK_REQUIRED": "", - "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "", - "RECOVER_TWO_FACTOR": "", + "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "Was macht der andere Dienst besser?", + "RECOVER_TWO_FACTOR": "Zwei-Faktor wiederherstellen", "at": "", "AUTH_NEXT": "Weiter", "AUTH_DOWNLOAD_MOBILE_APP": "", @@ -556,48 +556,48 @@ "SELECT_COLLECTION": "Album auswählen", "PIN_ALBUM": "Album anheften", "UNPIN_ALBUM": "Album lösen", - "DOWNLOAD_COMPLETE": "", - "DOWNLOADING_COLLECTION": "", - "DOWNLOAD_FAILED": "", - "DOWNLOAD_PROGRESS": "", - "CHRISTMAS": "", - "CHRISTMAS_EVE": "", + "DOWNLOAD_COMPLETE": "Download abgeschlossen", + "DOWNLOADING_COLLECTION": "Lade {{name}} herunter", + "DOWNLOAD_FAILED": "Herunterladen fehlgeschlagen", + "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} Dateien", + "CHRISTMAS": "Weihnachten", + "CHRISTMAS_EVE": "Heiligabend", "NEW_YEAR": "", "NEW_YEAR_EVE": "", - "IMAGE": "", - "VIDEO": "", - "LIVE_PHOTO": "", - "CONVERT": "", + "IMAGE": "Bild", + "VIDEO": "Video", + "LIVE_PHOTO": "Live-Foto", + "CONVERT": "Konvertieren", "CONFIRM_EDITOR_CLOSE_MESSAGE": "", "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", - "BRIGHTNESS": "", - "CONTRAST": "", - "SATURATION": "", - "BLUR": "", - "INVERT_COLORS": "", - "ASPECT_RATIO": "", - "SQUARE": "", - "ROTATE_LEFT": "", - "ROTATE_RIGHT": "", - "FLIP_VERTICALLY": "", - "FLIP_HORIZONTALLY": "", + "BRIGHTNESS": "Helligkeit", + "CONTRAST": "Kontrast", + "SATURATION": "Sättigung", + "BLUR": "Weichzeichnen", + "INVERT_COLORS": "Farben invertieren", + "ASPECT_RATIO": "Seitenverhältnis", + "SQUARE": "Quadrat", + "ROTATE_LEFT": "Nach links drehen", + "ROTATE_RIGHT": "Nach rechts drehen", + "FLIP_VERTICALLY": "Vertikal spiegeln", + "FLIP_HORIZONTALLY": "Horizontal spiegeln", "DOWNLOAD_EDITED": "", - "SAVE_A_COPY_TO_ENTE": "", - "RESTORE_ORIGINAL": "", - "TRANSFORM": "", - "COLORS": "", - "FLIP": "", - "ROTATION": "", - "RESET": "", - "PHOTO_EDITOR": "", + "SAVE_A_COPY_TO_ENTE": "Kopie in Ente speichern", + "RESTORE_ORIGINAL": "Original wiederherstellen", + "TRANSFORM": "Transformieren", + "COLORS": "Farben", + "FLIP": "Spiegeln", + "ROTATION": "Drehen", + "RESET": "Zurücksetzen", + "PHOTO_EDITOR": "Foto-Editor", "FASTER_UPLOAD": "", "FASTER_UPLOAD_DESCRIPTION": "", "MAGIC_SEARCH_STATUS": "", - "INDEXED_ITEMS": "", - "CAST_ALBUM_TO_TV": "", - "ENTER_CAST_PIN_CODE": "", - "PAIR_DEVICE_TO_TV": "", - "TV_NOT_FOUND": "", + "INDEXED_ITEMS": "Indizierte Elemente", + "CAST_ALBUM_TO_TV": "Album auf Fernseher wiedergeben", + "ENTER_CAST_PIN_CODE": "Gib den Code auf dem Fernseher unten ein, um dieses Gerät zu koppeln.", + "PAIR_DEVICE_TO_TV": "Geräte koppeln", + "TV_NOT_FOUND": "Fernseher nicht gefunden. Hast du die PIN korrekt eingegeben?", "AUTO_CAST_PAIR": "", "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "", "PAIR_WITH_PIN": "", @@ -605,21 +605,21 @@ "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "", "VISIT_CAST_ENTE_IO": "", "CAST_AUTO_PAIR_FAILED": "", - "FREEHAND": "", + "FREEHAND": "Freihand", "APPLY_CROP": "", "PHOTO_EDIT_REQUIRED_TO_SAVE": "", - "PASSKEYS": "", - "DELETE_PASSKEY": "", - "DELETE_PASSKEY_CONFIRMATION": "", - "RENAME_PASSKEY": "", - "ADD_PASSKEY": "", - "ENTER_PASSKEY_NAME": "", - "PASSKEYS_DESCRIPTION": "", - "CREATED_AT": "", - "PASSKEY_LOGIN_FAILED": "", - "PASSKEY_LOGIN_URL_INVALID": "", - "PASSKEY_LOGIN_ERRORED": "", - "TRY_AGAIN": "", - "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", - "LOGIN_WITH_PASSKEY": "" + "PASSKEYS": "Passkeys", + "DELETE_PASSKEY": "Passkey löschen", + "DELETE_PASSKEY_CONFIRMATION": "Bist du sicher, dass du diesen Passkey löschen willst? Dieser Vorgang ist nicht umkehrbar.", + "RENAME_PASSKEY": "Passkey umbenennen", + "ADD_PASSKEY": "Passkey hinzufügen", + "ENTER_PASSKEY_NAME": "Passkey-Namen eingeben", + "PASSKEYS_DESCRIPTION": "Passkeys sind ein moderner und sicherer zweiter Faktor für dein Ente-Konto. Sie nutzen die biometrische Authentifizierung des Geräts für Komfort und Sicherheit.", + "CREATED_AT": "Erstellt am", + "PASSKEY_LOGIN_FAILED": "Passkey-Anmeldung fehlgeschlagen", + "PASSKEY_LOGIN_URL_INVALID": "Die Anmelde-URL ist ungültig.", + "PASSKEY_LOGIN_ERRORED": "Ein Fehler trat auf beim Anmelden mit dem Passkey auf.", + "TRY_AGAIN": "Erneut versuchen", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "Folge den Schritten in deinem Browser, um mit dem Anmelden fortzufahren.", + "LOGIN_WITH_PASSKEY": "Mit Passkey anmelden" } diff --git a/web/packages/next/locales/sv-SE/translation.json b/web/packages/next/locales/sv-SE/translation.json index afc9b4ec41..77462524d5 100644 --- a/web/packages/next/locales/sv-SE/translation.json +++ b/web/packages/next/locales/sv-SE/translation.json @@ -12,7 +12,7 @@ "ENTER_NAME": "Ange namn", "PUBLIC_UPLOADER_NAME_MESSAGE": "", "ENTER_EMAIL": "Ange e-postadress", - "EMAIL_ERROR": "", + "EMAIL_ERROR": "Ange en giltig e-postadress", "REQUIRED": "", "EMAIL_SENT": "", "CHECK_INBOX": "", @@ -80,7 +80,7 @@ "DOWNLOAD_HIDDEN_ITEMS": "", "COPY_OPTION": "", "TOGGLE_FULLSCREEN": "", - "ZOOM_IN_OUT": "", + "ZOOM_IN_OUT": "Zooma in/ut", "PREVIOUS": "", "NEXT": "", "TITLE_PHOTOS": "", From 22c080c2aa2a89d80db3a07dc92365b0f50e9b8c Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Tue, 16 Apr 2024 02:03:30 +0000 Subject: [PATCH 58/84] New Crowdin translations by GitHub Action --- auth/lib/l10n/arb/app_de.arb | 4 ++++ auth/lib/l10n/arb/app_it.arb | 4 +++- auth/lib/l10n/arb/app_pt.arb | 7 +++++++ auth/lib/l10n/arb/app_sv.arb | 1 + 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/auth/lib/l10n/arb/app_de.arb b/auth/lib/l10n/arb/app_de.arb index a7cd560439..f3ea23b512 100644 --- a/auth/lib/l10n/arb/app_de.arb +++ b/auth/lib/l10n/arb/app_de.arb @@ -113,12 +113,14 @@ "copied": "Kopiert", "pleaseTryAgain": "Bitte versuchen Sie es erneut", "existingUser": "Bestehender Benutzer", + "newUser": "Neu bei Ente", "delete": "Löschen", "enterYourPasswordHint": "Geben Sie Ihr Passwort ein", "forgotPassword": "Passwort vergessen", "oops": "Hopla", "suggestFeatures": "Features vorschlagen", "faq": "FAQ", + "faq_q_1": "Wie sicher ist Auth?", "faq_q_2": "Kann ich auf meine Codes auf dem Desktop zugreifen?", "faq_a_2": "Sie können auf Ihre Codes im Web via auth.ente.io zugreifen.", "faq_q_3": "Wie kann ich Codes löschen?", @@ -193,6 +195,7 @@ "recoveryKeySaveDescription": "Wir speichern diesen Schlüssel nicht. Sichern sie dieses diesen Schlüssel bestehend aus 24 Wörtern an einem sicheren Platz.", "doThisLater": "Auf später verschieben", "saveKey": "Schlüssel speichern", + "save": "Speichern", "back": "Zurück", "createAccount": "Account erstellen", "passwordStrength": "Passwortstärke: {passwordStrengthValue}", @@ -400,6 +403,7 @@ "doNotSignOut": "Nicht abmelden", "hearUsWhereTitle": "Wie hast du von Ente erfahren? (optional)", "hearUsExplanation": "Wir tracken keine App-Installationen. Es würde uns jedoch helfen, wenn du uns mitteilst, wie du von uns erfahren hast!", + "recoveryKeySaved": "Wiederherstellungsschlüssel im Downloads-Ordner gespeichert!", "waitingForBrowserRequest": "Warten auf Browseranfrage...", "waitingForVerification": "Warte auf Bestätigung...", "passkey": "Passkey", diff --git a/auth/lib/l10n/arb/app_it.arb b/auth/lib/l10n/arb/app_it.arb index 473b3a2b3b..e35fd11dc0 100644 --- a/auth/lib/l10n/arb/app_it.arb +++ b/auth/lib/l10n/arb/app_it.arb @@ -190,6 +190,7 @@ "recoveryKeySaveDescription": "Non memorizziamo questa chiave, per favore salva questa chiave di 24 parole in un posto sicuro.", "doThisLater": "Fallo più tardi", "saveKey": "Salva chiave", + "save": "Salva", "back": "Indietro", "createAccount": "Crea account", "passwordStrength": "Forza password: {passwordStrengthValue}", @@ -396,5 +397,6 @@ "signOutOtherDevices": "Esci dagli altri dispositivi", "doNotSignOut": "Non uscire", "hearUsWhereTitle": "Dove hai sentito parlare di Ente? (opzionale)", - "hearUsExplanation": "Non teniamo traccia delle installazioni dell'app. Sarebbe utile se ci dicessi dove ci hai trovato!" + "hearUsExplanation": "Non teniamo traccia delle installazioni dell'app. Sarebbe utile se ci dicessi dove ci hai trovato!", + "passkey": "Passkey" } \ No newline at end of file diff --git a/auth/lib/l10n/arb/app_pt.arb b/auth/lib/l10n/arb/app_pt.arb index 06e2c0bb4a..b27a018fba 100644 --- a/auth/lib/l10n/arb/app_pt.arb +++ b/auth/lib/l10n/arb/app_pt.arb @@ -78,12 +78,14 @@ "data": "Dados", "importCodes": "Importar códigos", "importTypePlainText": "Texto simples", + "importTypeEnteEncrypted": "Exportação Ente criptografada", "passwordForDecryptingExport": "Senha para descriptografar a exportação", "passwordEmptyError": "O campo senha não pode estar vazio", "importFromApp": "Importar códigos do {appName}", "importGoogleAuthGuide": "Exporte suas contas do Google Authenticator para um QR code usando a opção \"Transferir contas\". Então, usando outro dispositivo, escaneie o QR code.\n\nDica: Você pode usar a câmera do seu notebook para fotografar o QR code.", "importSelectJsonFile": "Selecione o arquivo JSON", "importSelectAppExport": "Selecione o arquivo de exportação do aplicativo {appName}", + "importEnteEncGuide": "Selecione o arquivo JSON criptografado exportado do Ente", "importRaivoGuide": "Use a opção \"Exportar OTPs para arquivo Zip\" nas configurações do Raivo.\n\nExtraia o arquivo zip e importe o arquivo JSON.", "importBitwardenGuide": "Use a opção \"Exportar cofre\" nas configurações do Bitwarden e importe o arquivo JSON não criptografado.", "importAegisGuide": "Use a opção \"Exportar cofre\" nas Configurações do Aegis.\n\nSe o seu cofre estiver criptografado, você precisará inserir a senha do cofre para descriptografá-lo.", @@ -113,18 +115,22 @@ "copied": "Copiado", "pleaseTryAgain": "Por favor, tente novamente", "existingUser": "Usuário Existente", + "newUser": "Novo no Ente", "delete": "Excluir", "enterYourPasswordHint": "Insira sua senha", "forgotPassword": "Esqueci a senha", "oops": "Oops", "suggestFeatures": "Sugerir funcionalidades", "faq": "Perguntas frequentes", + "faq_q_1": "Quão seguro é o Auth?", + "faq_a_1": "Todos os códigos que você faz backup via Auth são armazenados criptografados de ponta a ponta. Isso significa que somente você pode acessar seus códigos. Nossos aplicativos são de código aberto e nossa criptografia foi auditada externamente.", "faq_q_2": "Eu posso acessar meus códigos no computador?", "faq_a_2": "Você pode acessar seus códigos na web em auth.ente.io.", "faq_q_3": "Como faço para excluir códigos?", "faq_a_3": "Você pode excluir um código deslizando para a esquerda sobre esse item.", "faq_q_4": "Como posso apoiar este projeto?", "faq_a_4": "Você pode apoiar o desenvolvimento deste projeto assinando nosso aplicativo de Fotos em ente.io.", + "faq_q_5": "Como posso ativar o bloqueio facial no Auth", "faq_a_5": "Você pode ativar o bloqueio facial em Configurações → Segurança → Tela de bloqueio.", "somethingWentWrongMessage": "Algo deu errado. Por favor, tente outra vez", "leaveFamily": "Sair da família", @@ -344,6 +350,7 @@ "deleteCodeAuthMessage": "Autenticar para excluir o código", "showQRAuthMessage": "Autenticar para mostrar o QR code", "confirmAccountDeleteTitle": "Confirmar exclusão de conta", + "confirmAccountDeleteMessage": "Esta conta está vinculada a outros aplicativos Ente, se você usa algum.\n\nSeus dados enviados, em todos os aplicativos Ente, serão agendados para exclusão, e sua conta será excluída permanentemente.", "androidBiometricHint": "Verificar identidade", "@androidBiometricHint": { "description": "Hint message advising the user how to authenticate with biometrics. It is used on Android side. Maximum 60 characters." diff --git a/auth/lib/l10n/arb/app_sv.arb b/auth/lib/l10n/arb/app_sv.arb index d1dc39e056..cfb41d7bdc 100644 --- a/auth/lib/l10n/arb/app_sv.arb +++ b/auth/lib/l10n/arb/app_sv.arb @@ -61,6 +61,7 @@ "incorrectPasswordTitle": "Felaktigt lösenord", "welcomeBack": "Välkommen tillbaka!", "changePassword": "Ändra lösenord", + "importCodes": "Importera koder", "cancel": "Avbryt", "yes": "Ja", "no": "Nej", From d7b0beb949a8e2e659f7669f5598a5189e92113d Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 16 Apr 2024 09:03:35 +0530 Subject: [PATCH 59/84] [web] Clear search bar state when value is falsey Updates https://github.com/ente-io/ente/pull/1453 so that we also clear the existing state by calling the setFoo methods even when value is falsey. --- .../src/components/Search/SearchBar/searchInput/index.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/web/apps/photos/src/components/Search/SearchBar/searchInput/index.tsx b/web/apps/photos/src/components/Search/SearchBar/searchInput/index.tsx index 4e9552a1df..d7cf151e66 100644 --- a/web/apps/photos/src/components/Search/SearchBar/searchInput/index.tsx +++ b/web/apps/photos/src/components/Search/SearchBar/searchInput/index.tsx @@ -56,10 +56,8 @@ export default function SearchInput(props: Iprops) { const [value, setValue] = useState(null); const appContext = useContext(AppContext); const handleChange = (value: SearchOption) => { - if (value) { - setValue(value); - setQuery(value.label); - } + setValue(value); + setQuery(value?.label); blur(); }; From 74b9a2a408c28cc7f7c8a80bcffa5d663408c7bb Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 16 Apr 2024 09:14:58 +0530 Subject: [PATCH 60/84] [server] Specify a default for apps.public-albums local.yaml is only loaded in the local environment, and will not be used in production. To avoid specifying it in both production and local configurations, use it as a default specified in the code instead (that's the pattern we're using in other places too from what I remember, maybe we should refactor that too, but that's a bigger task not tied to this change). **Tested by** On a local dev cluster - Not specifying anything and ensuring that the default is picked - Specifying an override in museum.yaml and verifying that is used instead --- server/configurations/local.yaml | 7 +++++-- server/pkg/repo/public_collection.go | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/server/configurations/local.yaml b/server/configurations/local.yaml index 0e456a53af..7785f56019 100644 --- a/server/configurations/local.yaml +++ b/server/configurations/local.yaml @@ -73,8 +73,11 @@ http: # Specify the base endpoints for various apps apps: - public-albums: "https://albums.ente.io" - + # Default is https://albums.ente.io + # + # If you're running a self hosted instance and wish to serve public links, + # set this to the URL where your albums web app is running. + public-albums: # Database connection parameters db: diff --git a/server/pkg/repo/public_collection.go b/server/pkg/repo/public_collection.go index d4aa81bf29..6c6106a77a 100644 --- a/server/pkg/repo/public_collection.go +++ b/server/pkg/repo/public_collection.go @@ -23,7 +23,7 @@ type PublicCollectionRepository struct { // NewPublicCollectionRepository .. func NewPublicCollectionRepository(db *sql.DB, albumHost string) *PublicCollectionRepository { if albumHost == "" { - panic("albumHost can not be empty") + albumHost = "https://albums.ente.io" } return &PublicCollectionRepository{ DB: db, From 1e202a76c437714c18b05de512718b775b3cd55a Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 16 Apr 2024 09:39:43 +0530 Subject: [PATCH 61/84] Works if we don't stream --- web/apps/photos/src/utils/native-stream.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/web/apps/photos/src/utils/native-stream.ts b/web/apps/photos/src/utils/native-stream.ts index 65db237b30..12b55f68b1 100644 --- a/web/apps/photos/src/utils/native-stream.ts +++ b/web/apps/photos/src/utils/native-stream.ts @@ -15,6 +15,11 @@ * @param stream The stream which should be written into the file. * */ export const writeStream = async (path: string, stream: ReadableStream) => { + + const response = new Response(stream); + const blob = await response.blob(); + // const ReadableStream() + // The duplex parameter needs to be set to 'half' when streaming requests. // // Currently browsers, and specifically in our case, since this code runs @@ -24,11 +29,11 @@ export const writeStream = async (path: string, stream: ReadableStream) => { const req = new Request(`stream://write${path}`, { // GET can't have a body method: "POST", - body: stream, - // @ts-expect-error TypeScript's libdom.d.ts does not include the + body: blob, + // @ts-expect-erroXXX TypeScript's libdom.d.ts does not include the // "duplex" parameter, e.g. see // https://github.com/node-fetch/node-fetch/issues/1769. - duplex: "half", + // duplex: "half", }); const res = await fetch(req); if (!res.ok) From d53a4a14b83cc17259b83fdb24cc5af01657ad02 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 16 Apr 2024 09:46:55 +0530 Subject: [PATCH 62/84] Try another reader --- desktop/src/main/stream.ts | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/desktop/src/main/stream.ts b/desktop/src/main/stream.ts index 2d0eaa62c0..73b04b2cd0 100644 --- a/desktop/src/main/stream.ts +++ b/desktop/src/main/stream.ts @@ -39,11 +39,19 @@ export const registerStreamProtocol = () => { try { // await writeStream(path, request.body); console.log("starting stream"); - let c = 0; - for await (const p of request.body as any) { - if (c == 327680) console.log(p); - fs.appendFile(path, p); - c += p.length; + // let c = 0; + // for await (const p of request.body as any) { + // if (c == 327680) console.log(p); + // fs.appendFile(path, p); + // c += p.length; + // } + const reader = request.body.getReader(); + // eslint-disable-next-line no-constant-condition + while (true) { + const { value, done } = await reader.read(); + if (done) break; + console.log(`Received ${value.length} bytes`); + fs.appendFile(path, value); } console.log("ending stream"); From 81d1563c3d2c806da58920a26ad96e842e02c817 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 16 Apr 2024 10:17:34 +0530 Subject: [PATCH 63/84] Also reproducible on latest beta --- desktop/package.json | 2 +- desktop/yarn.lock | 8 +++---- web/apps/photos/src/utils/native-stream.ts | 28 ++++++++++++++++++++++ 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/desktop/package.json b/desktop/package.json index 69d54f75be..1f368c4b98 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -39,7 +39,7 @@ "@typescript-eslint/eslint-plugin": "^7", "@typescript-eslint/parser": "^7", "concurrently": "^8", - "electron": "^29", + "electron": "30.0.0-beta.8", "electron-builder": "^24", "electron-builder-notarize": "^1.5", "eslint": "^8", diff --git a/desktop/yarn.lock b/desktop/yarn.lock index a5b86f1eb3..0c314db0f7 100644 --- a/desktop/yarn.lock +++ b/desktop/yarn.lock @@ -1214,10 +1214,10 @@ electron-updater@^6.1: semver "^7.3.8" tiny-typed-emitter "^2.1.0" -electron@^29: - version "29.3.0" - resolved "https://registry.yarnpkg.com/electron/-/electron-29.3.0.tgz#8e65cb08e9c0952c66d3196e1b5c811c43b8c5b0" - integrity sha512-ZxFKm0/v48GSoBuO3DdnMlCYXefEUKUHLMsKxyXY4nZGgzbBKpF/X8haZa2paNj23CLfsCKBOtfc2vsEQiOOsA== +electron@30.0.0-beta.8: + version "30.0.0-beta.8" + resolved "https://registry.yarnpkg.com/electron/-/electron-30.0.0-beta.8.tgz#c4430b9cb662ec147709deaededefe6d7dcc0522" + integrity sha512-G2IMMxUVJopiskD5G5iCQh71u1Emp+Q7nS1bWRU/9sK8bKwW1qtyBb3qoq0X9bd7y0LuKUb79AOr3Ix+J6EKaQ== dependencies: "@electron/get" "^2.0.0" "@types/node" "^20.9.0" diff --git a/web/apps/photos/src/utils/native-stream.ts b/web/apps/photos/src/utils/native-stream.ts index 12b55f68b1..91934059b6 100644 --- a/web/apps/photos/src/utils/native-stream.ts +++ b/web/apps/photos/src/utils/native-stream.ts @@ -15,7 +15,35 @@ * @param stream The stream which should be written into the file. * */ export const writeStream = async (path: string, stream: ReadableStream) => { + // return writeStreamOneShot(path, stream) + // The duplex parameter needs to be set to 'half' when streaming requests. + // + // Currently browsers, and specifically in our case, since this code runs + // only within our desktop (Electron) app, Chromium, don't support 'full' + // duplex mode (i.e. streaming both the request and the response). + // https://developer.chrome.com/docs/capabilities/web-apis/fetch-streaming-requests + const req = new Request(`stream://write${path}`, { + // GET can't have a body + method: "POST", + headers: { "Content-Type": "application/octet-stream" }, + body: stream, + // @ts-expect-error TypeScript's libdom.d.ts does not include the + // "duplex" parameter, e.g. see + // https://github.com/node-fetch/node-fetch/issues/1769. + duplex: "half", + }); + const res = await fetch(req); + if (!res.ok) + throw new Error( + `Failed to write stream to ${path}: HTTP ${res.status}`, + ); +}; + +export const writeStreamOneShot = async ( + path: string, + stream: ReadableStream, +) => { const response = new Response(stream); const blob = await response.blob(); // const ReadableStream() From 450e494a5e245d7e1553e65ca1320583f0318814 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 16 Apr 2024 11:33:03 +0530 Subject: [PATCH 64/84] Throwing darts --- desktop/src/main.ts | 39 +++++++++++++++++--- web/apps/photos/src/utils/native-stream.ts | 41 +++++++++++++++++++++- 2 files changed, 75 insertions(+), 5 deletions(-) diff --git a/desktop/src/main.ts b/desktop/src/main.ts index 8526e23632..72e2b8233e 100644 --- a/desktop/src/main.ts +++ b/desktop/src/main.ts @@ -132,12 +132,43 @@ const registerPrivilegedSchemes = () => { // TODO(MR): Remove the commented bits if we don't end up // needing them by the time the IPC refactoring is done. - // Prevent the insecure origin issues when fetching this + // standard: true, + // // Prevent the insecure origin issues when fetching this // secure: true, - // Allow the web fetch API in the renderer to use this scheme. - supportFetchAPI: true, - // Allow it to be used with video tags. + // // Allow the web fetch API in the renderer to use this scheme. + // supportFetchAPI: true, + // // Allow it to be used with video tags. // stream: true, + standard: true, + /** + * Default false. + */ + secure: true, + /** + * Default false. + */ + bypassCSP: true, + /** + * Default false. + */ + allowServiceWorkers: true, + /** + * Default false. + */ + supportFetchAPI: true, + /** + * Default false. + */ + corsEnabled: true, + /** + * Default false. + */ + stream: true, + /** + * Enable V8 code cache for the scheme, only works when `standard` is also set to + * true. Default false. + */ + codeCache: true, }, }, ]); diff --git a/web/apps/photos/src/utils/native-stream.ts b/web/apps/photos/src/utils/native-stream.ts index 91934059b6..0176a2b7cc 100644 --- a/web/apps/photos/src/utils/native-stream.ts +++ b/web/apps/photos/src/utils/native-stream.ts @@ -15,6 +15,10 @@ * @param stream The stream which should be written into the file. * */ export const writeStream = async (path: string, stream: ReadableStream) => { + writeStream_1("/tmp/1.txt", testStream()); +}; + +export const writeStream_1 = async (path: string, stream: ReadableStream) => { // return writeStreamOneShot(path, stream) // The duplex parameter needs to be set to 'half' when streaming requests. @@ -26,7 +30,10 @@ export const writeStream = async (path: string, stream: ReadableStream) => { const req = new Request(`stream://write${path}`, { // GET can't have a body method: "POST", - headers: { "Content-Type": "application/octet-stream" }, + headers: { + "Content-Type": "application/octet-stream", + "Content-Length": "1128608", + }, body: stream, // @ts-expect-error TypeScript's libdom.d.ts does not include the // "duplex" parameter, e.g. see @@ -40,6 +47,38 @@ export const writeStream = async (path: string, stream: ReadableStream) => { ); }; +const testStream = () => { + return new ReadableStream({ + async start(controller) { + const send = (count: number, char: string) => + controller.enqueue( + new TextEncoder().encode(Array(count).fill(char).join("")), + ); + + send(65536, "1"); + send(65536, "2"); + send(65536, "3"); + send(65536, "4"); + send(65536, "5"); + send(65536, "6"); + send(65536, "7"); + send(65536, "8"); + send(65536, "9"); + send(65536, "1"); + send(65536, "2"); + send(65536, "3"); + send(65536, "4"); + send(65536, "5"); + send(65536, "6"); + send(65536, "7"); + send(65536, "8"); + send(14496, "9"); + + controller.close(); + }, + }); +}; + export const writeStreamOneShot = async ( path: string, stream: ReadableStream, From 3b5a2e9d2a1f3e193755f03a0c1316fff0bc4e99 Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Tue, 16 Apr 2024 11:36:35 +0530 Subject: [PATCH 65/84] [photos] v0.8.82 --- mobile/pubspec.yaml | 2 +- mobile/thirdparty/flutter | 1 + mobile/thirdparty/isar | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) create mode 160000 mobile/thirdparty/flutter create mode 160000 mobile/thirdparty/isar diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index f1575bdf8b..89bee933b1 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -12,7 +12,7 @@ description: ente photos application # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 0.8.81+601 +version: 0.8.82+602 publish_to: none environment: diff --git a/mobile/thirdparty/flutter b/mobile/thirdparty/flutter new file mode 160000 index 0000000000..ba39319843 --- /dev/null +++ b/mobile/thirdparty/flutter @@ -0,0 +1 @@ +Subproject commit ba393198430278b6595976de84fe170f553cc728 diff --git a/mobile/thirdparty/isar b/mobile/thirdparty/isar new file mode 160000 index 0000000000..6643d064ab --- /dev/null +++ b/mobile/thirdparty/isar @@ -0,0 +1 @@ +Subproject commit 6643d064abf22606b6c6a741ea873e4781115ef4 From 4cede0feb009ce8c91596ff9063b370515c59c1c Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Tue, 16 Apr 2024 11:46:37 +0530 Subject: [PATCH 66/84] Remove submodules --- mobile/thirdparty/flutter | 1 - mobile/thirdparty/isar | 1 - 2 files changed, 2 deletions(-) delete mode 160000 mobile/thirdparty/flutter delete mode 160000 mobile/thirdparty/isar diff --git a/mobile/thirdparty/flutter b/mobile/thirdparty/flutter deleted file mode 160000 index ba39319843..0000000000 --- a/mobile/thirdparty/flutter +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ba393198430278b6595976de84fe170f553cc728 diff --git a/mobile/thirdparty/isar b/mobile/thirdparty/isar deleted file mode 160000 index 6643d064ab..0000000000 --- a/mobile/thirdparty/isar +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6643d064abf22606b6c6a741ea873e4781115ef4 From 2403c19f7067d39c524eae71691ac2897c4790ab Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 16 Apr 2024 14:46:13 +0530 Subject: [PATCH 67/84] Add a temporary fallback --- desktop/package.json | 2 +- desktop/src/main.ts | 39 +--------- desktop/src/main/services/ffmpeg.ts | 2 +- desktop/src/main/services/imageProcessor.ts | 2 +- desktop/src/main/services/ml-clip.ts | 2 +- desktop/src/main/services/ml.ts | 2 +- desktop/src/main/stream.ts | 19 +---- desktop/yarn.lock | 8 +- web/apps/photos/src/utils/native-stream.ts | 82 ++++----------------- 9 files changed, 29 insertions(+), 129 deletions(-) diff --git a/desktop/package.json b/desktop/package.json index 1f368c4b98..69d54f75be 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -39,7 +39,7 @@ "@typescript-eslint/eslint-plugin": "^7", "@typescript-eslint/parser": "^7", "concurrently": "^8", - "electron": "30.0.0-beta.8", + "electron": "^29", "electron-builder": "^24", "electron-builder-notarize": "^1.5", "eslint": "^8", diff --git a/desktop/src/main.ts b/desktop/src/main.ts index 72e2b8233e..8526e23632 100644 --- a/desktop/src/main.ts +++ b/desktop/src/main.ts @@ -132,43 +132,12 @@ const registerPrivilegedSchemes = () => { // TODO(MR): Remove the commented bits if we don't end up // needing them by the time the IPC refactoring is done. - // standard: true, - // // Prevent the insecure origin issues when fetching this + // Prevent the insecure origin issues when fetching this // secure: true, - // // Allow the web fetch API in the renderer to use this scheme. - // supportFetchAPI: true, - // // Allow it to be used with video tags. - // stream: true, - standard: true, - /** - * Default false. - */ - secure: true, - /** - * Default false. - */ - bypassCSP: true, - /** - * Default false. - */ - allowServiceWorkers: true, - /** - * Default false. - */ + // Allow the web fetch API in the renderer to use this scheme. supportFetchAPI: true, - /** - * Default false. - */ - corsEnabled: true, - /** - * Default false. - */ - stream: true, - /** - * Enable V8 code cache for the scheme, only works when `standard` is also set to - * true. Default false. - */ - codeCache: true, + // Allow it to be used with video tags. + // stream: true, }, }, ]); diff --git a/desktop/src/main/services/ffmpeg.ts b/desktop/src/main/services/ffmpeg.ts index 3072d5ee7b..2597bae60f 100644 --- a/desktop/src/main/services/ffmpeg.ts +++ b/desktop/src/main/services/ffmpeg.ts @@ -2,8 +2,8 @@ import pathToFfmpeg from "ffmpeg-static"; import { existsSync } from "node:fs"; import fs from "node:fs/promises"; import { ElectronFile } from "../../types/ipc"; -import { writeStream } from "../stream"; import log from "../log"; +import { writeStream } from "../stream"; import { generateTempFilePath, getTempDirPath } from "../temp"; import { execAsync } from "../util"; diff --git a/desktop/src/main/services/imageProcessor.ts b/desktop/src/main/services/imageProcessor.ts index d87fb0c5f2..696119d80f 100644 --- a/desktop/src/main/services/imageProcessor.ts +++ b/desktop/src/main/services/imageProcessor.ts @@ -2,9 +2,9 @@ import { existsSync } from "fs"; import fs from "node:fs/promises"; import path from "path"; import { CustomErrors, ElectronFile } from "../../types/ipc"; -import { writeStream } from "../stream"; import log from "../log"; import { isPlatform } from "../platform"; +import { writeStream } from "../stream"; import { generateTempFilePath } from "../temp"; import { execAsync, isDev } from "../util"; import { deleteTempFile } from "./ffmpeg"; diff --git a/desktop/src/main/services/ml-clip.ts b/desktop/src/main/services/ml-clip.ts index af8198a3cf..46af2552bc 100644 --- a/desktop/src/main/services/ml-clip.ts +++ b/desktop/src/main/services/ml-clip.ts @@ -11,8 +11,8 @@ import fs from "node:fs/promises"; import * as ort from "onnxruntime-node"; import Tokenizer from "../../thirdparty/clip-bpe-ts/mod"; import { CustomErrors } from "../../types/ipc"; -import { writeStream } from "../stream"; import log from "../log"; +import { writeStream } from "../stream"; import { generateTempFilePath } from "../temp"; import { deleteTempFile } from "./ffmpeg"; import { diff --git a/desktop/src/main/services/ml.ts b/desktop/src/main/services/ml.ts index e1d68e2ddd..60e8241e16 100644 --- a/desktop/src/main/services/ml.ts +++ b/desktop/src/main/services/ml.ts @@ -15,8 +15,8 @@ import { existsSync } from "fs"; import fs from "node:fs/promises"; import path from "node:path"; import * as ort from "onnxruntime-node"; -import { writeStream } from "../stream"; import log from "../log"; +import { writeStream } from "../stream"; /** * Download the model named {@link modelName} if we don't already have it. diff --git a/desktop/src/main/stream.ts b/desktop/src/main/stream.ts index 73b04b2cd0..8ddb80dc6a 100644 --- a/desktop/src/main/stream.ts +++ b/desktop/src/main/stream.ts @@ -37,24 +37,7 @@ export const registerStreamProtocol = () => { /* host-pathname----- */ case "write": try { - // await writeStream(path, request.body); - console.log("starting stream"); - // let c = 0; - // for await (const p of request.body as any) { - // if (c == 327680) console.log(p); - // fs.appendFile(path, p); - // c += p.length; - // } - const reader = request.body.getReader(); - // eslint-disable-next-line no-constant-condition - while (true) { - const { value, done } = await reader.read(); - if (done) break; - console.log(`Received ${value.length} bytes`); - fs.appendFile(path, value); - } - console.log("ending stream"); - + await writeStream(path, request.body); return new Response("", { status: 200 }); } catch (e) { log.error(`Failed to write stream for ${url}`, e); diff --git a/desktop/yarn.lock b/desktop/yarn.lock index 0c314db0f7..a5b86f1eb3 100644 --- a/desktop/yarn.lock +++ b/desktop/yarn.lock @@ -1214,10 +1214,10 @@ electron-updater@^6.1: semver "^7.3.8" tiny-typed-emitter "^2.1.0" -electron@30.0.0-beta.8: - version "30.0.0-beta.8" - resolved "https://registry.yarnpkg.com/electron/-/electron-30.0.0-beta.8.tgz#c4430b9cb662ec147709deaededefe6d7dcc0522" - integrity sha512-G2IMMxUVJopiskD5G5iCQh71u1Emp+Q7nS1bWRU/9sK8bKwW1qtyBb3qoq0X9bd7y0LuKUb79AOr3Ix+J6EKaQ== +electron@^29: + version "29.3.0" + resolved "https://registry.yarnpkg.com/electron/-/electron-29.3.0.tgz#8e65cb08e9c0952c66d3196e1b5c811c43b8c5b0" + integrity sha512-ZxFKm0/v48GSoBuO3DdnMlCYXefEUKUHLMsKxyXY4nZGgzbBKpF/X8haZa2paNj23CLfsCKBOtfc2vsEQiOOsA== dependencies: "@electron/get" "^2.0.0" "@types/node" "^20.9.0" diff --git a/web/apps/photos/src/utils/native-stream.ts b/web/apps/photos/src/utils/native-stream.ts index 0176a2b7cc..7dba1acf9c 100644 --- a/web/apps/photos/src/utils/native-stream.ts +++ b/web/apps/photos/src/utils/native-stream.ts @@ -15,12 +15,19 @@ * @param stream The stream which should be written into the file. * */ export const writeStream = async (path: string, stream: ReadableStream) => { - writeStream_1("/tmp/1.txt", testStream()); -}; - -export const writeStream_1 = async (path: string, stream: ReadableStream) => { - // return writeStreamOneShot(path, stream) + // TODO(MR): This doesn't currently work. + // + // Not sure what I'm doing wrong here; I've opened an issue upstream + // https://github.com/electron/electron/issues/41872 + // + // A gist with a minimal reproduction + // https://gist.github.com/mnvr/e08d9f4876fb8400b7615347b4d268eb + // + // Meanwhile, write the complete body in one go (this'll eventually run into + // memory failures with large files - just a temporary stopgap to get the + // code to work). + /* // The duplex parameter needs to be set to 'half' when streaming requests. // // Currently browsers, and specifically in our case, since this code runs @@ -30,78 +37,19 @@ export const writeStream_1 = async (path: string, stream: ReadableStream) => { const req = new Request(`stream://write${path}`, { // GET can't have a body method: "POST", - headers: { - "Content-Type": "application/octet-stream", - "Content-Length": "1128608", - }, body: stream, // @ts-expect-error TypeScript's libdom.d.ts does not include the // "duplex" parameter, e.g. see // https://github.com/node-fetch/node-fetch/issues/1769. duplex: "half", }); - const res = await fetch(req); - if (!res.ok) - throw new Error( - `Failed to write stream to ${path}: HTTP ${res.status}`, - ); -}; + */ -const testStream = () => { - return new ReadableStream({ - async start(controller) { - const send = (count: number, char: string) => - controller.enqueue( - new TextEncoder().encode(Array(count).fill(char).join("")), - ); - - send(65536, "1"); - send(65536, "2"); - send(65536, "3"); - send(65536, "4"); - send(65536, "5"); - send(65536, "6"); - send(65536, "7"); - send(65536, "8"); - send(65536, "9"); - send(65536, "1"); - send(65536, "2"); - send(65536, "3"); - send(65536, "4"); - send(65536, "5"); - send(65536, "6"); - send(65536, "7"); - send(65536, "8"); - send(14496, "9"); - - controller.close(); - }, - }); -}; - -export const writeStreamOneShot = async ( - path: string, - stream: ReadableStream, -) => { - const response = new Response(stream); - const blob = await response.blob(); - // const ReadableStream() - - // The duplex parameter needs to be set to 'half' when streaming requests. - // - // Currently browsers, and specifically in our case, since this code runs - // only within our desktop (Electron) app, Chromium, don't support 'full' - // duplex mode (i.e. streaming both the request and the response). - // https://developer.chrome.com/docs/capabilities/web-apis/fetch-streaming-requests const req = new Request(`stream://write${path}`, { - // GET can't have a body method: "POST", - body: blob, - // @ts-expect-erroXXX TypeScript's libdom.d.ts does not include the - // "duplex" parameter, e.g. see - // https://github.com/node-fetch/node-fetch/issues/1769. - // duplex: "half", + body: await new Response(stream).blob(), }); + const res = await fetch(req); if (!res.ok) throw new Error( From cd4b2a6810849c0b0189026492e5ab50b503403c Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 16 Apr 2024 15:26:35 +0530 Subject: [PATCH 68/84] Inline --- web/apps/photos/src/services/watchFolder/utils.ts | 5 ----- .../photos/src/services/watchFolder/watchFolderService.ts | 7 ++++++- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/web/apps/photos/src/services/watchFolder/utils.ts b/web/apps/photos/src/services/watchFolder/utils.ts index bd6ceb853c..e69de29bb2 100644 --- a/web/apps/photos/src/services/watchFolder/utils.ts +++ b/web/apps/photos/src/services/watchFolder/utils.ts @@ -1,5 +0,0 @@ -export const getParentFolderName = (filePath: string) => { - const folderPath = filePath.substring(0, filePath.lastIndexOf("/")); - const folderName = folderPath.substring(folderPath.lastIndexOf("/") + 1); - return folderName; -}; diff --git a/web/apps/photos/src/services/watchFolder/watchFolderService.ts b/web/apps/photos/src/services/watchFolder/watchFolderService.ts index 791aed445d..ac0ca3a885 100644 --- a/web/apps/photos/src/services/watchFolder/watchFolderService.ts +++ b/web/apps/photos/src/services/watchFolder/watchFolderService.ts @@ -15,7 +15,6 @@ import { groupFilesBasedOnCollectionID } from "utils/file"; import { getValidFilesToUpload } from "utils/watch"; import { removeFromCollection } from "../collectionService"; import { getLocalFiles } from "../fileService"; -import { getParentFolderName } from "./utils"; import { diskFileAddedCallback, diskFileRemovedCallback, @@ -642,3 +641,9 @@ class watchFolderService { } export default new watchFolderService(); + +export const getParentFolderName = (filePath: string) => { + const folderPath = filePath.substring(0, filePath.lastIndexOf("/")); + const folderName = folderPath.substring(folderPath.lastIndexOf("/") + 1); + return folderName; +}; From cf889b24af1d2d417355a73ad01049b85782017a Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 16 Apr 2024 15:28:23 +0530 Subject: [PATCH 69/84] Inline --- .../photos/src/services/watchFolder/utils.ts | 0 .../watchFolder/watchFolderEventHandlers.ts | 73 ----------------- .../watchFolder/watchFolderService.ts | 82 +++++++++++++++++-- 3 files changed, 74 insertions(+), 81 deletions(-) delete mode 100644 web/apps/photos/src/services/watchFolder/utils.ts delete mode 100644 web/apps/photos/src/services/watchFolder/watchFolderEventHandlers.ts diff --git a/web/apps/photos/src/services/watchFolder/utils.ts b/web/apps/photos/src/services/watchFolder/utils.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/web/apps/photos/src/services/watchFolder/watchFolderEventHandlers.ts b/web/apps/photos/src/services/watchFolder/watchFolderEventHandlers.ts deleted file mode 100644 index ba4ad62ee3..0000000000 --- a/web/apps/photos/src/services/watchFolder/watchFolderEventHandlers.ts +++ /dev/null @@ -1,73 +0,0 @@ -import log from "@/next/log"; -import { ElectronFile } from "types/upload"; -import { EventQueueItem } from "types/watchFolder"; -import watchFolderService from "./watchFolderService"; - -export async function diskFileAddedCallback(file: ElectronFile) { - try { - const collectionNameAndFolderPath = - await watchFolderService.getCollectionNameAndFolderPath(file.path); - - if (!collectionNameAndFolderPath) { - return; - } - - const { collectionName, folderPath } = collectionNameAndFolderPath; - - const event: EventQueueItem = { - type: "upload", - collectionName, - folderPath, - files: [file], - }; - watchFolderService.pushEvent(event); - log.info( - `added (upload) to event queue, collectionName:${event.collectionName} folderPath:${event.folderPath}, filesCount: ${event.files.length}`, - ); - } catch (e) { - log.error("error while calling diskFileAddedCallback", e); - } -} - -export async function diskFileRemovedCallback(filePath: string) { - try { - const collectionNameAndFolderPath = - await watchFolderService.getCollectionNameAndFolderPath(filePath); - - if (!collectionNameAndFolderPath) { - return; - } - - const { collectionName, folderPath } = collectionNameAndFolderPath; - - const event: EventQueueItem = { - type: "trash", - collectionName, - folderPath, - paths: [filePath], - }; - watchFolderService.pushEvent(event); - log.info( - `added (trash) to event queue collectionName:${event.collectionName} folderPath:${event.folderPath} , pathsCount: ${event.paths.length}`, - ); - } catch (e) { - log.error("error while calling diskFileRemovedCallback", e); - } -} - -export async function diskFolderRemovedCallback(folderPath: string) { - try { - const mappings = await watchFolderService.getWatchMappings(); - const mapping = mappings.find( - (mapping) => mapping.folderPath === folderPath, - ); - if (!mapping) { - log.info(`folder not found in mappings, ${folderPath}`); - throw Error(`Watch mapping not found`); - } - watchFolderService.pushTrashedDir(folderPath); - log.info(`added trashedDir, ${folderPath}`); - } catch (e) { - log.error("error while calling diskFolderRemovedCallback", e); - } -} diff --git a/web/apps/photos/src/services/watchFolder/watchFolderService.ts b/web/apps/photos/src/services/watchFolder/watchFolderService.ts index ac0ca3a885..386b3efa60 100644 --- a/web/apps/photos/src/services/watchFolder/watchFolderService.ts +++ b/web/apps/photos/src/services/watchFolder/watchFolderService.ts @@ -15,13 +15,8 @@ import { groupFilesBasedOnCollectionID } from "utils/file"; import { getValidFilesToUpload } from "utils/watch"; import { removeFromCollection } from "../collectionService"; import { getLocalFiles } from "../fileService"; -import { - diskFileAddedCallback, - diskFileRemovedCallback, - diskFolderRemovedCallback, -} from "./watchFolderEventHandlers"; -class watchFolderService { +class WatchFolderService { private eventQueue: EventQueueItem[] = []; private currentEvent: EventQueueItem; private currentlySyncedMapping: WatchMapping; @@ -640,10 +635,81 @@ class watchFolderService { } } -export default new watchFolderService(); +const watchFolderService = new WatchFolderService(); -export const getParentFolderName = (filePath: string) => { +export default watchFolderService; + +const getParentFolderName = (filePath: string) => { const folderPath = filePath.substring(0, filePath.lastIndexOf("/")); const folderName = folderPath.substring(folderPath.lastIndexOf("/") + 1); return folderName; }; + +async function diskFileAddedCallback(file: ElectronFile) { + try { + const collectionNameAndFolderPath = + await watchFolderService.getCollectionNameAndFolderPath(file.path); + + if (!collectionNameAndFolderPath) { + return; + } + + const { collectionName, folderPath } = collectionNameAndFolderPath; + + const event: EventQueueItem = { + type: "upload", + collectionName, + folderPath, + files: [file], + }; + watchFolderService.pushEvent(event); + log.info( + `added (upload) to event queue, collectionName:${event.collectionName} folderPath:${event.folderPath}, filesCount: ${event.files.length}`, + ); + } catch (e) { + log.error("error while calling diskFileAddedCallback", e); + } +} + +async function diskFileRemovedCallback(filePath: string) { + try { + const collectionNameAndFolderPath = + await watchFolderService.getCollectionNameAndFolderPath(filePath); + + if (!collectionNameAndFolderPath) { + return; + } + + const { collectionName, folderPath } = collectionNameAndFolderPath; + + const event: EventQueueItem = { + type: "trash", + collectionName, + folderPath, + paths: [filePath], + }; + watchFolderService.pushEvent(event); + log.info( + `added (trash) to event queue collectionName:${event.collectionName} folderPath:${event.folderPath} , pathsCount: ${event.paths.length}`, + ); + } catch (e) { + log.error("error while calling diskFileRemovedCallback", e); + } +} + +async function diskFolderRemovedCallback(folderPath: string) { + try { + const mappings = await watchFolderService.getWatchMappings(); + const mapping = mappings.find( + (mapping) => mapping.folderPath === folderPath, + ); + if (!mapping) { + log.info(`folder not found in mappings, ${folderPath}`); + throw Error(`Watch mapping not found`); + } + watchFolderService.pushTrashedDir(folderPath); + log.info(`added trashedDir, ${folderPath}`); + } catch (e) { + log.error("error while calling diskFolderRemovedCallback", e); + } +} From 96ea99640153d5c5bd6ec28790a1d0784659bdc5 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 16 Apr 2024 15:29:56 +0530 Subject: [PATCH 70/84] Inline --- .../watchFolder/watchFolderService.ts | 25 +++++++++++++++++- web/apps/photos/src/utils/watch/index.ts | 26 ------------------- 2 files changed, 24 insertions(+), 27 deletions(-) delete mode 100644 web/apps/photos/src/utils/watch/index.ts diff --git a/web/apps/photos/src/services/watchFolder/watchFolderService.ts b/web/apps/photos/src/services/watchFolder/watchFolderService.ts index 386b3efa60..e039eb3dee 100644 --- a/web/apps/photos/src/services/watchFolder/watchFolderService.ts +++ b/web/apps/photos/src/services/watchFolder/watchFolderService.ts @@ -12,7 +12,7 @@ import { WatchMappingSyncedFile, } from "types/watchFolder"; import { groupFilesBasedOnCollectionID } from "utils/file"; -import { getValidFilesToUpload } from "utils/watch"; +import { isSystemFile } from "utils/upload"; import { removeFromCollection } from "../collectionService"; import { getLocalFiles } from "../fileService"; @@ -713,3 +713,26 @@ async function diskFolderRemovedCallback(folderPath: string) { log.error("error while calling diskFolderRemovedCallback", e); } } + +export function getValidFilesToUpload( + files: ElectronFile[], + mapping: WatchMapping, +) { + const uniqueFilePaths = new Set(); + return files.filter((file) => { + if (!isSystemFile(file) && !isSyncedOrIgnoredFile(file, mapping)) { + if (!uniqueFilePaths.has(file.path)) { + uniqueFilePaths.add(file.path); + return true; + } + } + return false; + }); +} + +function isSyncedOrIgnoredFile(file: ElectronFile, mapping: WatchMapping) { + return ( + mapping.ignoredFiles.includes(file.path) || + mapping.syncedFiles.find((f) => f.path === file.path) + ); +} diff --git a/web/apps/photos/src/utils/watch/index.ts b/web/apps/photos/src/utils/watch/index.ts deleted file mode 100644 index eb16780ddc..0000000000 --- a/web/apps/photos/src/utils/watch/index.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { ElectronFile } from "types/upload"; -import { WatchMapping } from "types/watchFolder"; -import { isSystemFile } from "utils/upload"; - -function isSyncedOrIgnoredFile(file: ElectronFile, mapping: WatchMapping) { - return ( - mapping.ignoredFiles.includes(file.path) || - mapping.syncedFiles.find((f) => f.path === file.path) - ); -} - -export function getValidFilesToUpload( - files: ElectronFile[], - mapping: WatchMapping, -) { - const uniqueFilePaths = new Set(); - return files.filter((file) => { - if (!isSystemFile(file) && !isSyncedOrIgnoredFile(file, mapping)) { - if (!uniqueFilePaths.has(file.path)) { - uniqueFilePaths.add(file.path); - return true; - } - } - return false; - }); -} From 8fbff7e3a39777f9d2e035e6d89ead54b16df8a1 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 16 Apr 2024 15:33:47 +0530 Subject: [PATCH 71/84] Inline --- .../WatchFolder/mappingEntry/entryHeading.tsx | 23 ------- .../WatchFolder/mappingEntry/index.tsx | 66 +++++++++++++++++-- .../mappingEntry/mappingEntryOptions.tsx | 33 ---------- .../WatchFolder/mappingList/index.tsx | 54 ++++++++++++++- .../noMappingsContent/checkmarkIcon.tsx | 15 ----- .../noMappingsContent/noMappingsContent.tsx | 33 ---------- 6 files changed, 112 insertions(+), 112 deletions(-) delete mode 100644 web/apps/photos/src/components/WatchFolder/mappingEntry/entryHeading.tsx delete mode 100644 web/apps/photos/src/components/WatchFolder/mappingEntry/mappingEntryOptions.tsx delete mode 100644 web/apps/photos/src/components/WatchFolder/mappingList/noMappingsContent/checkmarkIcon.tsx delete mode 100644 web/apps/photos/src/components/WatchFolder/mappingList/noMappingsContent/noMappingsContent.tsx diff --git a/web/apps/photos/src/components/WatchFolder/mappingEntry/entryHeading.tsx b/web/apps/photos/src/components/WatchFolder/mappingEntry/entryHeading.tsx deleted file mode 100644 index b34e4277ff..0000000000 --- a/web/apps/photos/src/components/WatchFolder/mappingEntry/entryHeading.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { FlexWrapper } from "@ente/shared/components/Container"; -import { CircularProgress, Typography } from "@mui/material"; -import { AppContext } from "pages/_app"; -import { useContext } from "react"; -import watchFolderService from "services/watchFolder/watchFolderService"; -import { WatchMapping } from "types/watchFolder"; - -interface Iprops { - mapping: WatchMapping; -} - -export function EntryHeading({ mapping }: Iprops) { - const appContext = useContext(AppContext); - return ( - - {mapping.rootFolderName} - {appContext.isFolderSyncRunning && - watchFolderService.isMappingSyncInProgress(mapping) && ( - - )} - - ); -} diff --git a/web/apps/photos/src/components/WatchFolder/mappingEntry/index.tsx b/web/apps/photos/src/components/WatchFolder/mappingEntry/index.tsx index 8193946995..c511848662 100644 --- a/web/apps/photos/src/components/WatchFolder/mappingEntry/index.tsx +++ b/web/apps/photos/src/components/WatchFolder/mappingEntry/index.tsx @@ -1,26 +1,34 @@ import { + FlexWrapper, HorizontalFlex, SpaceBetweenFlex, } from "@ente/shared/components/Container"; +import OverflowMenu from "@ente/shared/components/OverflowMenu/menu"; +import { OverflowMenuOption } from "@ente/shared/components/OverflowMenu/option"; +import DoNotDisturbOutlinedIcon from "@mui/icons-material/DoNotDisturbOutlined"; import FolderCopyOutlinedIcon from "@mui/icons-material/FolderCopyOutlined"; import FolderOpenIcon from "@mui/icons-material/FolderOpen"; -import { Tooltip, Typography } from "@mui/material"; +import MoreHorizIcon from "@mui/icons-material/MoreHoriz"; +import { CircularProgress, Tooltip, Typography } from "@mui/material"; +import { UPLOAD_STRATEGY } from "constants/upload"; import { t } from "i18next"; import { AppContext } from "pages/_app"; -import React from "react"; +import React, { useContext } from "react"; +import watchFolderService from "services/watchFolder/watchFolderService"; import { WatchMapping } from "types/watchFolder"; import { EntryContainer } from "../styledComponents"; - -import { UPLOAD_STRATEGY } from "constants/upload"; import { EntryHeading } from "./entryHeading"; import MappingEntryOptions from "./mappingEntryOptions"; -interface Iprops { +interface MappingEntryProps { mapping: WatchMapping; handleRemoveMapping: (mapping: WatchMapping) => void; } -export function MappingEntry({ mapping, handleRemoveMapping }: Iprops) { +export function MappingEntry({ + mapping, + handleRemoveMapping, +}: MappingEntryProps) { const appContext = React.useContext(AppContext); const stopWatching = () => { @@ -67,3 +75,49 @@ export function MappingEntry({ mapping, handleRemoveMapping }: Iprops) { ); } + +interface EntryHeadingProps { + mapping: WatchMapping; +} + +export function EntryHeading({ mapping }: EntryHeadingProps) { + const appContext = useContext(AppContext); + return ( + + {mapping.rootFolderName} + {appContext.isFolderSyncRunning && + watchFolderService.isMappingSyncInProgress(mapping) && ( + + )} + + ); +} + +interface MappingEntryOptionsProps { + confirmStopWatching: () => void; +} + +export default function MappingEntryOptions({ + confirmStopWatching, +}: MappingEntryOptionsProps) { + return ( + + theme.colors.background.elevated2, + }, + }} + ariaControls={"watch-mapping-option"} + triggerButtonIcon={} + > + } + > + {t("STOP_WATCHING")} + + + ); +} diff --git a/web/apps/photos/src/components/WatchFolder/mappingEntry/mappingEntryOptions.tsx b/web/apps/photos/src/components/WatchFolder/mappingEntry/mappingEntryOptions.tsx deleted file mode 100644 index 4f3cdc56d1..0000000000 --- a/web/apps/photos/src/components/WatchFolder/mappingEntry/mappingEntryOptions.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { t } from "i18next"; - -import OverflowMenu from "@ente/shared/components/OverflowMenu/menu"; -import { OverflowMenuOption } from "@ente/shared/components/OverflowMenu/option"; -import DoNotDisturbOutlinedIcon from "@mui/icons-material/DoNotDisturbOutlined"; -import MoreHorizIcon from "@mui/icons-material/MoreHoriz"; - -interface Iprops { - confirmStopWatching: () => void; -} - -export default function MappingEntryOptions({ confirmStopWatching }: Iprops) { - return ( - - theme.colors.background.elevated2, - }, - }} - ariaControls={"watch-mapping-option"} - triggerButtonIcon={} - > - } - > - {t("STOP_WATCHING")} - - - ); -} diff --git a/web/apps/photos/src/components/WatchFolder/mappingList/index.tsx b/web/apps/photos/src/components/WatchFolder/mappingList/index.tsx index f2c7b781c7..97d2f56ca3 100644 --- a/web/apps/photos/src/components/WatchFolder/mappingList/index.tsx +++ b/web/apps/photos/src/components/WatchFolder/mappingList/index.tsx @@ -1,13 +1,22 @@ +import { FlexWrapper } from "@ente/shared/components/Container"; +import CheckIcon from "@mui/icons-material/Check"; +import { Stack, Typography } from "@mui/material"; +import { t } from "i18next"; import { WatchMapping } from "types/watchFolder"; +import { NoMappingsContainer } from "../../styledComponents"; import { MappingEntry } from "../mappingEntry"; import { MappingsContainer } from "../styledComponents"; import { NoMappingsContent } from "./noMappingsContent/noMappingsContent"; -interface Iprops { + +interface MappingListProps { mappings: WatchMapping[]; handleRemoveWatchMapping: (value: WatchMapping) => void; } -export function MappingList({ mappings, handleRemoveWatchMapping }: Iprops) { +export function MappingList({ + mappings, + handleRemoveWatchMapping, +}: MappingListProps) { return mappings.length === 0 ? ( ) : ( @@ -24,3 +33,44 @@ export function MappingList({ mappings, handleRemoveWatchMapping }: Iprops) { ); } + +export function NoMappingsContent() { + return ( + + + + {t("NO_FOLDERS_ADDED")} + + + {t("FOLDERS_AUTOMATICALLY_MONITORED")} + + + + + {t("UPLOAD_NEW_FILES_TO_ENTE")} + + + + + + {t("REMOVE_DELETED_FILES_FROM_ENTE")} + + + + + ); +} + +export function CheckmarkIcon() { + return ( + theme.palette.secondary.main, + }} + /> + ); +} diff --git a/web/apps/photos/src/components/WatchFolder/mappingList/noMappingsContent/checkmarkIcon.tsx b/web/apps/photos/src/components/WatchFolder/mappingList/noMappingsContent/checkmarkIcon.tsx deleted file mode 100644 index aedd79404a..0000000000 --- a/web/apps/photos/src/components/WatchFolder/mappingList/noMappingsContent/checkmarkIcon.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import CheckIcon from "@mui/icons-material/Check"; - -export function CheckmarkIcon() { - return ( - theme.palette.secondary.main, - }} - /> - ); -} diff --git a/web/apps/photos/src/components/WatchFolder/mappingList/noMappingsContent/noMappingsContent.tsx b/web/apps/photos/src/components/WatchFolder/mappingList/noMappingsContent/noMappingsContent.tsx deleted file mode 100644 index a5af6aff9d..0000000000 --- a/web/apps/photos/src/components/WatchFolder/mappingList/noMappingsContent/noMappingsContent.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { Stack, Typography } from "@mui/material"; -import { t } from "i18next"; - -import { FlexWrapper } from "@ente/shared/components/Container"; -import { NoMappingsContainer } from "../../styledComponents"; -import { CheckmarkIcon } from "./checkmarkIcon"; - -export function NoMappingsContent() { - return ( - - - - {t("NO_FOLDERS_ADDED")} - - - {t("FOLDERS_AUTOMATICALLY_MONITORED")} - - - - - {t("UPLOAD_NEW_FILES_TO_ENTE")} - - - - - - {t("REMOVE_DELETED_FILES_FROM_ENTE")} - - - - - ); -} From afec29d6e7e7688532b361603358bb288ddab897 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 16 Apr 2024 15:45:27 +0530 Subject: [PATCH 72/84] Inline and spruce --- .../src/components/Sidebar/UtilitySection.tsx | 2 +- .../photos/src/components/Upload/Uploader.tsx | 2 +- .../photos/src/components/WatchFolder.tsx | 363 ++++++++++++++++++ .../src/components/WatchFolder/index.tsx | 152 -------- .../WatchFolder/mappingEntry/index.tsx | 123 ------ .../WatchFolder/mappingList/index.tsx | 76 ---- .../WatchFolder/styledComponents.tsx | 23 -- .../src/services/upload/uploadManager.ts | 2 +- .../watchFolderService.ts => watch.ts} | 4 +- 9 files changed, 368 insertions(+), 379 deletions(-) create mode 100644 web/apps/photos/src/components/WatchFolder.tsx delete mode 100644 web/apps/photos/src/components/WatchFolder/index.tsx delete mode 100644 web/apps/photos/src/components/WatchFolder/mappingEntry/index.tsx delete mode 100644 web/apps/photos/src/components/WatchFolder/mappingList/index.tsx delete mode 100644 web/apps/photos/src/components/WatchFolder/styledComponents.tsx rename web/apps/photos/src/services/{watchFolder/watchFolderService.ts => watch.ts} (99%) diff --git a/web/apps/photos/src/components/Sidebar/UtilitySection.tsx b/web/apps/photos/src/components/Sidebar/UtilitySection.tsx index 904eab7474..c9c734cd98 100644 --- a/web/apps/photos/src/components/Sidebar/UtilitySection.tsx +++ b/web/apps/photos/src/components/Sidebar/UtilitySection.tsx @@ -24,7 +24,7 @@ import { import { getAccountsURL } from "@ente/shared/network/api"; import { THEME_COLOR } from "@ente/shared/themes/constants"; import { EnteMenuItem } from "components/Menu/EnteMenuItem"; -import WatchFolder from "components/WatchFolder"; +import { WatchFolder } from "components/WatchFolder"; import isElectron from "is-electron"; import { getAccountsToken } from "services/userService"; import { getDownloadAppMessage } from "utils/ui"; diff --git a/web/apps/photos/src/components/Upload/Uploader.tsx b/web/apps/photos/src/components/Upload/Uploader.tsx index 4d81b16122..bb3d4fd9d0 100644 --- a/web/apps/photos/src/components/Upload/Uploader.tsx +++ b/web/apps/photos/src/components/Upload/Uploader.tsx @@ -24,7 +24,7 @@ import { savePublicCollectionUploaderName, } from "services/publicCollectionService"; import uploadManager from "services/upload/uploadManager"; -import watchFolderService from "services/watchFolder/watchFolderService"; +import watchFolderService from "services/watch"; import { NotificationAttributes } from "types/Notification"; import { Collection } from "types/collection"; import { diff --git a/web/apps/photos/src/components/WatchFolder.tsx b/web/apps/photos/src/components/WatchFolder.tsx new file mode 100644 index 0000000000..8001dd9920 --- /dev/null +++ b/web/apps/photos/src/components/WatchFolder.tsx @@ -0,0 +1,363 @@ +import { + FlexWrapper, + HorizontalFlex, + SpaceBetweenFlex, + VerticallyCentered, +} from "@ente/shared/components/Container"; +import DialogTitleWithCloseButton from "@ente/shared/components/DialogBox/TitleWithCloseButton"; +import OverflowMenu from "@ente/shared/components/OverflowMenu/menu"; +import { OverflowMenuOption } from "@ente/shared/components/OverflowMenu/option"; +import CheckIcon from "@mui/icons-material/Check"; +import DoNotDisturbOutlinedIcon from "@mui/icons-material/DoNotDisturbOutlined"; +import FolderCopyOutlinedIcon from "@mui/icons-material/FolderCopyOutlined"; +import FolderOpenIcon from "@mui/icons-material/FolderOpen"; +import MoreHorizIcon from "@mui/icons-material/MoreHoriz"; +import { + Box, + Button, + CircularProgress, + Dialog, + DialogContent, + Stack, + Tooltip, + Typography, +} from "@mui/material"; +import { styled } from "@mui/material/styles"; +import UploadStrategyChoiceModal from "components/Upload/UploadStrategyChoiceModal"; +import { PICKED_UPLOAD_TYPE, UPLOAD_STRATEGY } from "constants/upload"; +import { t } from "i18next"; +import { AppContext } from "pages/_app"; +import React, { useContext, useEffect, useState } from "react"; +import watchFolderService from "services/watch"; +import { WatchMapping } from "types/watchFolder"; +import { getImportSuggestion } from "utils/upload"; + +interface WatchFolderProps { + open: boolean; + onClose: () => void; +} + +export const WatchFolder: React.FC = ({ open, onClose }) => { + const [mappings, setMappings] = useState([]); + const [inputFolderPath, setInputFolderPath] = useState(""); + const [choiceModalOpen, setChoiceModalOpen] = useState(false); + const appContext = useContext(AppContext); + + const electron = globalThis.electron; + + useEffect(() => { + if (!electron) return; + watchFolderService.getWatchMappings().then((m) => setMappings(m)); + }, []); + + useEffect(() => { + if ( + appContext.watchFolderFiles && + appContext.watchFolderFiles.length > 0 + ) { + handleFolderDrop(appContext.watchFolderFiles); + appContext.setWatchFolderFiles(null); + } + }, [appContext.watchFolderFiles]); + + const handleFolderDrop = async (folders: FileList) => { + for (let i = 0; i < folders.length; i++) { + const folder: any = folders[i]; + const path = (folder.path as string).replace(/\\/g, "/"); + if (await watchFolderService.isFolder(path)) { + await addFolderForWatching(path); + } + } + }; + + const addFolderForWatching = async (path: string) => { + if (!electron) return; + + setInputFolderPath(path); + const files = await electron.getDirFiles(path); + const analysisResult = getImportSuggestion( + PICKED_UPLOAD_TYPE.FOLDERS, + files, + ); + if (analysisResult.hasNestedFolders) { + setChoiceModalOpen(true); + } else { + handleAddWatchMapping(UPLOAD_STRATEGY.SINGLE_COLLECTION, path); + } + }; + + const handleAddFolderClick = async () => { + await handleFolderSelection(); + }; + + const handleFolderSelection = async () => { + const folderPath = await watchFolderService.selectFolder(); + if (folderPath) { + await addFolderForWatching(folderPath); + } + }; + + const handleAddWatchMapping = async ( + uploadStrategy: UPLOAD_STRATEGY, + folderPath?: string, + ) => { + folderPath = folderPath || inputFolderPath; + await watchFolderService.addWatchMapping( + folderPath.substring(folderPath.lastIndexOf("/") + 1), + folderPath, + uploadStrategy, + ); + setInputFolderPath(""); + setMappings(await watchFolderService.getWatchMappings()); + }; + + const handleRemoveWatchMapping = async (mapping: WatchMapping) => { + await watchFolderService.removeWatchMapping(mapping.folderPath); + setMappings(await watchFolderService.getWatchMappings()); + }; + + const closeChoiceModal = () => setChoiceModalOpen(false); + + const uploadToSingleCollection = () => { + closeChoiceModal(); + handleAddWatchMapping(UPLOAD_STRATEGY.SINGLE_COLLECTION); + }; + + const uploadToMultipleCollection = () => { + closeChoiceModal(); + handleAddWatchMapping(UPLOAD_STRATEGY.COLLECTION_PER_FOLDER); + }; + + return ( + <> + + + {t("WATCHED_FOLDERS")} + + + + + + + + + + + ); +}; + +const MappingsContainer = styled(Box)(() => ({ + height: "278px", + overflow: "auto", + "&::-webkit-scrollbar": { + width: "4px", + }, +})); + +const NoMappingsContainer = styled(VerticallyCentered)({ + textAlign: "left", + alignItems: "flex-start", + marginBottom: "32px", +}); + +const EntryContainer = styled(Box)({ + marginLeft: "12px", + marginRight: "6px", + marginBottom: "12px", +}); + +interface MappingListProps { + mappings: WatchMapping[]; + handleRemoveWatchMapping: (value: WatchMapping) => void; +} + +const MappingList: React.FC = ({ + mappings, + handleRemoveWatchMapping, +}) => { + return mappings.length === 0 ? ( + + ) : ( + + {mappings.map((mapping) => { + return ( + + ); + })} + + ); +}; + +const NoMappingsContent: React.FC = () => { + return ( + + + + {t("NO_FOLDERS_ADDED")} + + + {t("FOLDERS_AUTOMATICALLY_MONITORED")} + + + + + {t("UPLOAD_NEW_FILES_TO_ENTE")} + + + + + + {t("REMOVE_DELETED_FILES_FROM_ENTE")} + + + + + ); +}; + +const CheckmarkIcon: React.FC = () => { + return ( + theme.palette.secondary.main, + }} + /> + ); +}; + +interface MappingEntryProps { + mapping: WatchMapping; + handleRemoveMapping: (mapping: WatchMapping) => void; +} + +const MappingEntry: React.FC = ({ + mapping, + handleRemoveMapping, +}) => { + const appContext = React.useContext(AppContext); + + const stopWatching = () => { + handleRemoveMapping(mapping); + }; + + const confirmStopWatching = () => { + appContext.setDialogMessage({ + title: t("STOP_WATCHING_FOLDER"), + content: t("STOP_WATCHING_DIALOG_MESSAGE"), + close: { + text: t("CANCEL"), + variant: "secondary", + }, + proceed: { + action: stopWatching, + text: t("YES_STOP"), + variant: "critical", + }, + }); + }; + + return ( + + + {mapping && + mapping.uploadStrategy === UPLOAD_STRATEGY.SINGLE_COLLECTION ? ( + + + + ) : ( + + + + )} + + + + {mapping.folderPath} + + + + + + ); +}; + +interface EntryHeadingProps { + mapping: WatchMapping; +} + +const EntryHeading: React.FC = ({ mapping }) => { + const appContext = useContext(AppContext); + return ( + + {mapping.rootFolderName} + {appContext.isFolderSyncRunning && + watchFolderService.isMappingSyncInProgress(mapping) && ( + + )} + + ); +}; + +interface MappingEntryOptionsProps { + confirmStopWatching: () => void; +} + +const MappingEntryOptions: React.FC = ({ + confirmStopWatching, +}) => { + return ( + + theme.colors.background.elevated2, + }, + }} + ariaControls={"watch-mapping-option"} + triggerButtonIcon={} + > + } + > + {t("STOP_WATCHING")} + + + ); +}; diff --git a/web/apps/photos/src/components/WatchFolder/index.tsx b/web/apps/photos/src/components/WatchFolder/index.tsx deleted file mode 100644 index 4ccfd41387..0000000000 --- a/web/apps/photos/src/components/WatchFolder/index.tsx +++ /dev/null @@ -1,152 +0,0 @@ -import DialogTitleWithCloseButton from "@ente/shared/components/DialogBox/TitleWithCloseButton"; -import { Button, Dialog, DialogContent, Stack } from "@mui/material"; -import UploadStrategyChoiceModal from "components/Upload/UploadStrategyChoiceModal"; -import { PICKED_UPLOAD_TYPE, UPLOAD_STRATEGY } from "constants/upload"; -import { t } from "i18next"; -import { AppContext } from "pages/_app"; -import { useContext, useEffect, useState } from "react"; -import watchFolderService from "services/watchFolder/watchFolderService"; -import { WatchMapping } from "types/watchFolder"; -import { getImportSuggestion } from "utils/upload"; -import { MappingList } from "./mappingList"; - -interface Iprops { - open: boolean; - onClose: () => void; -} - -export default function WatchFolder({ open, onClose }: Iprops) { - const [mappings, setMappings] = useState([]); - const [inputFolderPath, setInputFolderPath] = useState(""); - const [choiceModalOpen, setChoiceModalOpen] = useState(false); - const appContext = useContext(AppContext); - - const electron = globalThis.electron; - - useEffect(() => { - if (!electron) return; - watchFolderService.getWatchMappings().then((m) => setMappings(m)); - }, []); - - useEffect(() => { - if ( - appContext.watchFolderFiles && - appContext.watchFolderFiles.length > 0 - ) { - handleFolderDrop(appContext.watchFolderFiles); - appContext.setWatchFolderFiles(null); - } - }, [appContext.watchFolderFiles]); - - const handleFolderDrop = async (folders: FileList) => { - for (let i = 0; i < folders.length; i++) { - const folder: any = folders[i]; - const path = (folder.path as string).replace(/\\/g, "/"); - if (await watchFolderService.isFolder(path)) { - await addFolderForWatching(path); - } - } - }; - - const addFolderForWatching = async (path: string) => { - if (!electron) return; - - setInputFolderPath(path); - const files = await electron.getDirFiles(path); - const analysisResult = getImportSuggestion( - PICKED_UPLOAD_TYPE.FOLDERS, - files, - ); - if (analysisResult.hasNestedFolders) { - setChoiceModalOpen(true); - } else { - handleAddWatchMapping(UPLOAD_STRATEGY.SINGLE_COLLECTION, path); - } - }; - - const handleAddFolderClick = async () => { - await handleFolderSelection(); - }; - - const handleFolderSelection = async () => { - const folderPath = await watchFolderService.selectFolder(); - if (folderPath) { - await addFolderForWatching(folderPath); - } - }; - - const handleAddWatchMapping = async ( - uploadStrategy: UPLOAD_STRATEGY, - folderPath?: string, - ) => { - folderPath = folderPath || inputFolderPath; - await watchFolderService.addWatchMapping( - folderPath.substring(folderPath.lastIndexOf("/") + 1), - folderPath, - uploadStrategy, - ); - setInputFolderPath(""); - setMappings(await watchFolderService.getWatchMappings()); - }; - - const handleRemoveWatchMapping = async (mapping: WatchMapping) => { - await watchFolderService.removeWatchMapping(mapping.folderPath); - setMappings(await watchFolderService.getWatchMappings()); - }; - - const closeChoiceModal = () => setChoiceModalOpen(false); - - const uploadToSingleCollection = () => { - closeChoiceModal(); - handleAddWatchMapping(UPLOAD_STRATEGY.SINGLE_COLLECTION); - }; - - const uploadToMultipleCollection = () => { - closeChoiceModal(); - handleAddWatchMapping(UPLOAD_STRATEGY.COLLECTION_PER_FOLDER); - }; - - return ( - <> - - - {t("WATCHED_FOLDERS")} - - - - - - - - - - - ); -} diff --git a/web/apps/photos/src/components/WatchFolder/mappingEntry/index.tsx b/web/apps/photos/src/components/WatchFolder/mappingEntry/index.tsx deleted file mode 100644 index c511848662..0000000000 --- a/web/apps/photos/src/components/WatchFolder/mappingEntry/index.tsx +++ /dev/null @@ -1,123 +0,0 @@ -import { - FlexWrapper, - HorizontalFlex, - SpaceBetweenFlex, -} from "@ente/shared/components/Container"; -import OverflowMenu from "@ente/shared/components/OverflowMenu/menu"; -import { OverflowMenuOption } from "@ente/shared/components/OverflowMenu/option"; -import DoNotDisturbOutlinedIcon from "@mui/icons-material/DoNotDisturbOutlined"; -import FolderCopyOutlinedIcon from "@mui/icons-material/FolderCopyOutlined"; -import FolderOpenIcon from "@mui/icons-material/FolderOpen"; -import MoreHorizIcon from "@mui/icons-material/MoreHoriz"; -import { CircularProgress, Tooltip, Typography } from "@mui/material"; -import { UPLOAD_STRATEGY } from "constants/upload"; -import { t } from "i18next"; -import { AppContext } from "pages/_app"; -import React, { useContext } from "react"; -import watchFolderService from "services/watchFolder/watchFolderService"; -import { WatchMapping } from "types/watchFolder"; -import { EntryContainer } from "../styledComponents"; -import { EntryHeading } from "./entryHeading"; -import MappingEntryOptions from "./mappingEntryOptions"; - -interface MappingEntryProps { - mapping: WatchMapping; - handleRemoveMapping: (mapping: WatchMapping) => void; -} - -export function MappingEntry({ - mapping, - handleRemoveMapping, -}: MappingEntryProps) { - const appContext = React.useContext(AppContext); - - const stopWatching = () => { - handleRemoveMapping(mapping); - }; - - const confirmStopWatching = () => { - appContext.setDialogMessage({ - title: t("STOP_WATCHING_FOLDER"), - content: t("STOP_WATCHING_DIALOG_MESSAGE"), - close: { - text: t("CANCEL"), - variant: "secondary", - }, - proceed: { - action: stopWatching, - text: t("YES_STOP"), - variant: "critical", - }, - }); - }; - - return ( - - - {mapping && - mapping.uploadStrategy === UPLOAD_STRATEGY.SINGLE_COLLECTION ? ( - - - - ) : ( - - - - )} - - - - {mapping.folderPath} - - - - - - ); -} - -interface EntryHeadingProps { - mapping: WatchMapping; -} - -export function EntryHeading({ mapping }: EntryHeadingProps) { - const appContext = useContext(AppContext); - return ( - - {mapping.rootFolderName} - {appContext.isFolderSyncRunning && - watchFolderService.isMappingSyncInProgress(mapping) && ( - - )} - - ); -} - -interface MappingEntryOptionsProps { - confirmStopWatching: () => void; -} - -export default function MappingEntryOptions({ - confirmStopWatching, -}: MappingEntryOptionsProps) { - return ( - - theme.colors.background.elevated2, - }, - }} - ariaControls={"watch-mapping-option"} - triggerButtonIcon={} - > - } - > - {t("STOP_WATCHING")} - - - ); -} diff --git a/web/apps/photos/src/components/WatchFolder/mappingList/index.tsx b/web/apps/photos/src/components/WatchFolder/mappingList/index.tsx deleted file mode 100644 index 97d2f56ca3..0000000000 --- a/web/apps/photos/src/components/WatchFolder/mappingList/index.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import { FlexWrapper } from "@ente/shared/components/Container"; -import CheckIcon from "@mui/icons-material/Check"; -import { Stack, Typography } from "@mui/material"; -import { t } from "i18next"; -import { WatchMapping } from "types/watchFolder"; -import { NoMappingsContainer } from "../../styledComponents"; -import { MappingEntry } from "../mappingEntry"; -import { MappingsContainer } from "../styledComponents"; -import { NoMappingsContent } from "./noMappingsContent/noMappingsContent"; - -interface MappingListProps { - mappings: WatchMapping[]; - handleRemoveWatchMapping: (value: WatchMapping) => void; -} - -export function MappingList({ - mappings, - handleRemoveWatchMapping, -}: MappingListProps) { - return mappings.length === 0 ? ( - - ) : ( - - {mappings.map((mapping) => { - return ( - - ); - })} - - ); -} - -export function NoMappingsContent() { - return ( - - - - {t("NO_FOLDERS_ADDED")} - - - {t("FOLDERS_AUTOMATICALLY_MONITORED")} - - - - - {t("UPLOAD_NEW_FILES_TO_ENTE")} - - - - - - {t("REMOVE_DELETED_FILES_FROM_ENTE")} - - - - - ); -} - -export function CheckmarkIcon() { - return ( - theme.palette.secondary.main, - }} - /> - ); -} diff --git a/web/apps/photos/src/components/WatchFolder/styledComponents.tsx b/web/apps/photos/src/components/WatchFolder/styledComponents.tsx deleted file mode 100644 index d507bbaa85..0000000000 --- a/web/apps/photos/src/components/WatchFolder/styledComponents.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { VerticallyCentered } from "@ente/shared/components/Container"; -import { Box } from "@mui/material"; -import { styled } from "@mui/material/styles"; - -export const MappingsContainer = styled(Box)(() => ({ - height: "278px", - overflow: "auto", - "&::-webkit-scrollbar": { - width: "4px", - }, -})); - -export const NoMappingsContainer = styled(VerticallyCentered)({ - textAlign: "left", - alignItems: "flex-start", - marginBottom: "32px", -}); - -export const EntryContainer = styled(Box)({ - marginLeft: "12px", - marginRight: "6px", - marginBottom: "12px", -}); diff --git a/web/apps/photos/src/services/upload/uploadManager.ts b/web/apps/photos/src/services/upload/uploadManager.ts index 82b761091f..d222999d8a 100644 --- a/web/apps/photos/src/services/upload/uploadManager.ts +++ b/web/apps/photos/src/services/upload/uploadManager.ts @@ -14,7 +14,7 @@ import { getPublicCollectionUID, } from "services/publicCollectionService"; import { getDisableCFUploadProxyFlag } from "services/userService"; -import watchFolderService from "services/watchFolder/watchFolderService"; +import watchFolderService from "services/watch"; import { Collection } from "types/collection"; import { EncryptedEnteFile, EnteFile } from "types/file"; import { SetFiles } from "types/gallery"; diff --git a/web/apps/photos/src/services/watchFolder/watchFolderService.ts b/web/apps/photos/src/services/watch.ts similarity index 99% rename from web/apps/photos/src/services/watchFolder/watchFolderService.ts rename to web/apps/photos/src/services/watch.ts index e039eb3dee..1c26addf09 100644 --- a/web/apps/photos/src/services/watchFolder/watchFolderService.ts +++ b/web/apps/photos/src/services/watch.ts @@ -13,8 +13,8 @@ import { } from "types/watchFolder"; import { groupFilesBasedOnCollectionID } from "utils/file"; import { isSystemFile } from "utils/upload"; -import { removeFromCollection } from "../collectionService"; -import { getLocalFiles } from "../fileService"; +import { removeFromCollection } from "./collectionService"; +import { getLocalFiles } from "./fileService"; class WatchFolderService { private eventQueue: EventQueueItem[] = []; From 9a6f3133b1bd00d8cd121b4caf70a0e2c68cee71 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 16 Apr 2024 16:17:27 +0530 Subject: [PATCH 73/84] Reduce API --- web/apps/photos/src/components/WatchFolder.tsx | 7 ++++--- web/apps/photos/src/services/watch.ts | 14 ++++++++------ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/web/apps/photos/src/components/WatchFolder.tsx b/web/apps/photos/src/components/WatchFolder.tsx index 8001dd9920..b5ff00b291 100644 --- a/web/apps/photos/src/components/WatchFolder.tsx +++ b/web/apps/photos/src/components/WatchFolder.tsx @@ -111,9 +111,10 @@ export const WatchFolder: React.FC = ({ open, onClose }) => { setMappings(await watchFolderService.getWatchMappings()); }; - const handleRemoveWatchMapping = async (mapping: WatchMapping) => { - await watchFolderService.removeWatchMapping(mapping.folderPath); - setMappings(await watchFolderService.getWatchMappings()); + const handleRemoveWatchMapping = (mapping: WatchMapping) => { + watchFolderService + .mappingsAfterRemovingFolder(mapping.folderPath) + .then((ms) => setMappings(ms)); }; const closeChoiceModal = () => setChoiceModalOpen(false); diff --git a/web/apps/photos/src/services/watch.ts b/web/apps/photos/src/services/watch.ts index 1c26addf09..2d5ef02287 100644 --- a/web/apps/photos/src/services/watch.ts +++ b/web/apps/photos/src/services/watch.ts @@ -1,3 +1,8 @@ +/** + * @file Interface with the Node.js layer of our desktop app to provide the + * watch folders functionality. + */ + import { ensureElectron } from "@/next/electron"; import log from "@/next/log"; import { UPLOAD_RESULT, UPLOAD_STRATEGY } from "constants/upload"; @@ -190,12 +195,9 @@ class WatchFolderService { } } - async removeWatchMapping(folderPath: string) { - try { - await ensureElectron().removeWatchMapping(folderPath); - } catch (e) { - log.error("error while removing watch mapping", e); - } + async mappingsAfterRemovingFolder(folderPath: string) { + await ensureElectron().removeWatchMapping(folderPath); + return await this.getWatchMappings(); } async getWatchMappings(): Promise { From 1fea50979364fbf2673f1ff8343ad8d28080f1c1 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 16 Apr 2024 16:25:49 +0530 Subject: [PATCH 74/84] Rename the type on the electron side --- desktop/src/main/ipc.ts | 6 +++--- desktop/src/main/services/watch.ts | 8 ++++---- desktop/src/preload.ts | 8 ++++---- desktop/src/types/ipc.ts | 30 +++++++++++++++--------------- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/desktop/src/main/ipc.ts b/desktop/src/main/ipc.ts index bd29057da0..a5de4514f9 100644 --- a/desktop/src/main/ipc.ts +++ b/desktop/src/main/ipc.ts @@ -10,7 +10,7 @@ import type { FSWatcher } from "chokidar"; import { ipcMain } from "electron/main"; -import type { ElectronFile, FILE_PATH_TYPE, WatchMapping } from "../types/ipc"; +import type { ElectronFile, FILE_PATH_TYPE, FolderWatch } from "../types/ipc"; import { selectDirectory, showUploadDirsDialog, @@ -242,13 +242,13 @@ export const attachFSWatchIPCHandlers = (watcher: FSWatcher) => { ipcMain.handle( "updateWatchMappingSyncedFiles", - (_, folderPath: string, files: WatchMapping["syncedFiles"]) => + (_, folderPath: string, files: FolderWatch["syncedFiles"]) => updateWatchMappingSyncedFiles(folderPath, files), ); ipcMain.handle( "updateWatchMappingIgnoredFiles", - (_, folderPath: string, files: WatchMapping["ignoredFiles"]) => + (_, folderPath: string, files: FolderWatch["ignoredFiles"]) => updateWatchMappingIgnoredFiles(folderPath, files), ); }; diff --git a/desktop/src/main/services/watch.ts b/desktop/src/main/services/watch.ts index 8a3414c58c..1d466d4156 100644 --- a/desktop/src/main/services/watch.ts +++ b/desktop/src/main/services/watch.ts @@ -1,6 +1,6 @@ import type { FSWatcher } from "chokidar"; import ElectronLog from "electron-log"; -import { WatchMapping, WatchStoreType } from "../../types/ipc"; +import { FolderWatch, WatchStoreType } from "../../types/ipc"; import { watchStore } from "../stores/watch.store"; export const addWatchMapping = async ( @@ -28,7 +28,7 @@ export const addWatchMapping = async ( setWatchMappings(watchMappings); }; -function isMappingPresent(watchMappings: WatchMapping[], folderPath: string) { +function isMappingPresent(watchMappings: FolderWatch[], folderPath: string) { const watchMapping = watchMappings?.find( (mapping) => mapping.folderPath === folderPath, ); @@ -59,7 +59,7 @@ export const removeWatchMapping = async ( export function updateWatchMappingSyncedFiles( folderPath: string, - files: WatchMapping["syncedFiles"], + files: FolderWatch["syncedFiles"], ): void { const watchMappings = getWatchMappings(); const watchMapping = watchMappings.find( @@ -76,7 +76,7 @@ export function updateWatchMappingSyncedFiles( export function updateWatchMappingIgnoredFiles( folderPath: string, - files: WatchMapping["ignoredFiles"], + files: FolderWatch["ignoredFiles"], ): void { const watchMappings = getWatchMappings(); const watchMapping = watchMappings.find( diff --git a/desktop/src/preload.ts b/desktop/src/preload.ts index ff2cf505af..2749fa50d2 100644 --- a/desktop/src/preload.ts +++ b/desktop/src/preload.ts @@ -45,7 +45,7 @@ import type { AppUpdateInfo, ElectronFile, FILE_PATH_TYPE, - WatchMapping, + FolderWatch, } from "./types/ipc"; // - General @@ -220,18 +220,18 @@ const addWatchMapping = ( const removeWatchMapping = (folderPath: string): Promise => ipcRenderer.invoke("removeWatchMapping", folderPath); -const getWatchMappings = (): Promise => +const getWatchMappings = (): Promise => ipcRenderer.invoke("getWatchMappings"); const updateWatchMappingSyncedFiles = ( folderPath: string, - files: WatchMapping["syncedFiles"], + files: FolderWatch["syncedFiles"], ): Promise => ipcRenderer.invoke("updateWatchMappingSyncedFiles", folderPath, files); const updateWatchMappingIgnoredFiles = ( folderPath: string, - files: WatchMapping["ignoredFiles"], + files: FolderWatch["ignoredFiles"], ): Promise => ipcRenderer.invoke("updateWatchMappingIgnoredFiles", folderPath, files); diff --git a/desktop/src/types/ipc.ts b/desktop/src/types/ipc.ts index 3dba231f20..3dae605a8e 100644 --- a/desktop/src/types/ipc.ts +++ b/desktop/src/types/ipc.ts @@ -5,6 +5,20 @@ * See [Note: types.ts <-> preload.ts <-> ipc.ts] */ +export interface FolderWatch { + rootFolderName: string; + uploadStrategy: number; + folderPath: string; + syncedFiles: FolderWatchSyncedFile[]; + ignoredFiles: string[]; +} + +export interface FolderWatchSyncedFile { + path: string; + uploadedFileID: number; + collectionID: number; +} + /** * Errors that have special semantics on the web side. * @@ -52,22 +66,8 @@ export interface ElectronFile { arrayBuffer: () => Promise; } -interface WatchMappingSyncedFile { - path: string; - uploadedFileID: number; - collectionID: number; -} - -export interface WatchMapping { - rootFolderName: string; - uploadStrategy: number; - folderPath: string; - syncedFiles: WatchMappingSyncedFile[]; - ignoredFiles: string[]; -} - export interface WatchStoreType { - mappings: WatchMapping[]; + mappings: FolderWatch[]; } export enum FILE_PATH_TYPE { From f775890af7904412f02ac0b41b70d35ccf58dec6 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 16 Apr 2024 16:35:30 +0530 Subject: [PATCH 75/84] Rename on the renderer side --- web/packages/next/types/file.ts | 14 ------------- web/packages/next/types/ipc.ts | 35 +++++++++++++++++++++++++++++---- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/web/packages/next/types/file.ts b/web/packages/next/types/file.ts index e7d3ced5aa..dc8a148e93 100644 --- a/web/packages/next/types/file.ts +++ b/web/packages/next/types/file.ts @@ -26,20 +26,6 @@ export interface DataStream { chunkCount: number; } -export interface WatchMappingSyncedFile { - path: string; - uploadedFileID: number; - collectionID: number; -} - -export interface WatchMapping { - rootFolderName: string; - folderPath: string; - uploadStrategy: UPLOAD_STRATEGY; - syncedFiles: WatchMappingSyncedFile[]; - ignoredFiles: string[]; -} - export interface EventQueueItem { type: "upload" | "trash"; folderPath: string; diff --git a/web/packages/next/types/ipc.ts b/web/packages/next/types/ipc.ts index 3477d745e4..85986b6391 100644 --- a/web/packages/next/types/ipc.ts +++ b/web/packages/next/types/ipc.ts @@ -3,7 +3,7 @@ // // See [Note: types.ts <-> preload.ts <-> ipc.ts] -import type { ElectronFile, WatchMapping } from "./file"; +import type { ElectronFile } from "./file"; export interface AppUpdateInfo { autoUpdatable: boolean; @@ -298,16 +298,16 @@ export interface Electron { removeWatchMapping: (folderPath: string) => Promise; - getWatchMappings: () => Promise; + getWatchMappings: () => Promise; updateWatchMappingSyncedFiles: ( folderPath: string, - files: WatchMapping["syncedFiles"], + files: FolderWatch["syncedFiles"], ) => Promise; updateWatchMappingIgnoredFiles: ( folderPath: string, - files: WatchMapping["ignoredFiles"], + files: FolderWatch["ignoredFiles"], ) => Promise; // - FS legacy @@ -332,3 +332,30 @@ export interface Electron { setToUploadCollection: (collectionName: string) => Promise; getDirFiles: (dirPath: string) => Promise; } + +/** + * A top level folder that was selected by the user for watching. + * + * The user can set up multiple such watches. Each of these can in turn be + * syncing multiple on disk folders to one or more (dependening on the + * {@link uploadStrategy}) Ente albums. + * + * This type is passed across the IPC boundary. It is persisted on the Node.js + * side. + */ +export interface FolderWatch { + rootFolderName: string; + uploadStrategy: number; + folderPath: string; + syncedFiles: FolderWatchSyncedFile[]; + ignoredFiles: string[]; +} + +/** + * An on-disk file that was synced as part of a folder watch. + */ +export interface FolderWatchSyncedFile { + path: string; + uploadedFileID: number; + collectionID: number; +} From 45942f79318833779678f03860a797d2a38381e0 Mon Sep 17 00:00:00 2001 From: Ashil <77285023+ashilkn@users.noreply.github.com> Date: Tue, 16 Apr 2024 17:49:28 +0530 Subject: [PATCH 76/84] [mob][photos] Search field fixes (#1464) ## Description See commits. --- mobile/lib/generated/intl/messages_cs.dart | 1 + mobile/lib/generated/intl/messages_de.dart | 1 + mobile/lib/generated/intl/messages_en.dart | 1 + mobile/lib/generated/intl/messages_es.dart | 1 + mobile/lib/generated/intl/messages_fr.dart | 1 + mobile/lib/generated/intl/messages_it.dart | 1 + mobile/lib/generated/intl/messages_ko.dart | 1 + mobile/lib/generated/intl/messages_nl.dart | 1 + mobile/lib/generated/intl/messages_no.dart | 1 + mobile/lib/generated/intl/messages_pl.dart | 1 + mobile/lib/generated/intl/messages_pt.dart | 1 + mobile/lib/generated/intl/messages_zh.dart | 1 + mobile/lib/generated/l10n.dart | 10 ++++++++++ mobile/lib/l10n/intl_cs.arb | 3 ++- mobile/lib/l10n/intl_de.arb | 3 ++- mobile/lib/l10n/intl_en.arb | 3 ++- mobile/lib/l10n/intl_es.arb | 3 ++- mobile/lib/l10n/intl_fr.arb | 3 ++- mobile/lib/l10n/intl_it.arb | 3 ++- mobile/lib/l10n/intl_ko.arb | 3 ++- mobile/lib/l10n/intl_nl.arb | 3 ++- mobile/lib/l10n/intl_no.arb | 3 ++- mobile/lib/l10n/intl_pl.arb | 3 ++- mobile/lib/l10n/intl_pt.arb | 3 ++- mobile/lib/l10n/intl_zh.arb | 3 ++- mobile/lib/ui/viewer/search/search_widget.dart | 12 +++++++----- 26 files changed, 53 insertions(+), 17 deletions(-) diff --git a/mobile/lib/generated/intl/messages_cs.dart b/mobile/lib/generated/intl/messages_cs.dart index 86ecd6893b..8db8489d33 100644 --- a/mobile/lib/generated/intl/messages_cs.dart +++ b/mobile/lib/generated/intl/messages_cs.dart @@ -55,6 +55,7 @@ class MessageLookup extends MessageLookupByLibrary { "Modify your query, or try searching for"), "moveToHiddenAlbum": MessageLookupByLibrary.simpleMessage("Move to hidden album"), + "search": MessageLookupByLibrary.simpleMessage("Search"), "selectALocation": MessageLookupByLibrary.simpleMessage("Select a location"), "selectALocationFirst": diff --git a/mobile/lib/generated/intl/messages_de.dart b/mobile/lib/generated/intl/messages_de.dart index 9005de2dcf..442cae9198 100644 --- a/mobile/lib/generated/intl/messages_de.dart +++ b/mobile/lib/generated/intl/messages_de.dart @@ -1213,6 +1213,7 @@ class MessageLookup extends MessageLookupByLibrary { "scanThisBarcodeWithnyourAuthenticatorApp": MessageLookupByLibrary.simpleMessage( "Scanne diesen Code mit \ndeiner Authentifizierungs-App"), + "search": MessageLookupByLibrary.simpleMessage("Search"), "searchAlbumsEmptySection": MessageLookupByLibrary.simpleMessage("Alben"), "searchByAlbumNameHint": diff --git a/mobile/lib/generated/intl/messages_en.dart b/mobile/lib/generated/intl/messages_en.dart index 59180d26ce..eef309aa5d 100644 --- a/mobile/lib/generated/intl/messages_en.dart +++ b/mobile/lib/generated/intl/messages_en.dart @@ -1175,6 +1175,7 @@ class MessageLookup extends MessageLookupByLibrary { "scanThisBarcodeWithnyourAuthenticatorApp": MessageLookupByLibrary.simpleMessage( "Scan this barcode with\nyour authenticator app"), + "search": MessageLookupByLibrary.simpleMessage("Search"), "searchAlbumsEmptySection": MessageLookupByLibrary.simpleMessage("Albums"), "searchByAlbumNameHint": diff --git a/mobile/lib/generated/intl/messages_es.dart b/mobile/lib/generated/intl/messages_es.dart index 5bba2d9a0a..a6294d4a43 100644 --- a/mobile/lib/generated/intl/messages_es.dart +++ b/mobile/lib/generated/intl/messages_es.dart @@ -1044,6 +1044,7 @@ class MessageLookup extends MessageLookupByLibrary { "scanThisBarcodeWithnyourAuthenticatorApp": MessageLookupByLibrary.simpleMessage( "Escanea este código QR con tu aplicación de autenticación"), + "search": MessageLookupByLibrary.simpleMessage("Search"), "searchByAlbumNameHint": MessageLookupByLibrary.simpleMessage("Nombre del álbum"), "searchByExamples": MessageLookupByLibrary.simpleMessage( diff --git a/mobile/lib/generated/intl/messages_fr.dart b/mobile/lib/generated/intl/messages_fr.dart index 5f21ec77b1..82125afcca 100644 --- a/mobile/lib/generated/intl/messages_fr.dart +++ b/mobile/lib/generated/intl/messages_fr.dart @@ -1182,6 +1182,7 @@ class MessageLookup extends MessageLookupByLibrary { "scanThisBarcodeWithnyourAuthenticatorApp": MessageLookupByLibrary.simpleMessage( "Scannez ce code-barres avec\nvotre application d\'authentification"), + "search": MessageLookupByLibrary.simpleMessage("Search"), "searchAlbumsEmptySection": MessageLookupByLibrary.simpleMessage("Albums"), "searchByAlbumNameHint": diff --git a/mobile/lib/generated/intl/messages_it.dart b/mobile/lib/generated/intl/messages_it.dart index c20931418f..e6db5b380f 100644 --- a/mobile/lib/generated/intl/messages_it.dart +++ b/mobile/lib/generated/intl/messages_it.dart @@ -1137,6 +1137,7 @@ class MessageLookup extends MessageLookupByLibrary { "scanThisBarcodeWithnyourAuthenticatorApp": MessageLookupByLibrary.simpleMessage( "Scansione questo codice QR\ncon la tua app di autenticazione"), + "search": MessageLookupByLibrary.simpleMessage("Search"), "searchByAlbumNameHint": MessageLookupByLibrary.simpleMessage("Nome album"), "searchByExamples": MessageLookupByLibrary.simpleMessage( diff --git a/mobile/lib/generated/intl/messages_ko.dart b/mobile/lib/generated/intl/messages_ko.dart index 15b4acf260..c91d849f6e 100644 --- a/mobile/lib/generated/intl/messages_ko.dart +++ b/mobile/lib/generated/intl/messages_ko.dart @@ -55,6 +55,7 @@ class MessageLookup extends MessageLookupByLibrary { "Modify your query, or try searching for"), "moveToHiddenAlbum": MessageLookupByLibrary.simpleMessage("Move to hidden album"), + "search": MessageLookupByLibrary.simpleMessage("Search"), "selectALocation": MessageLookupByLibrary.simpleMessage("Select a location"), "selectALocationFirst": diff --git a/mobile/lib/generated/intl/messages_nl.dart b/mobile/lib/generated/intl/messages_nl.dart index a86943e505..5f2b0903b5 100644 --- a/mobile/lib/generated/intl/messages_nl.dart +++ b/mobile/lib/generated/intl/messages_nl.dart @@ -1206,6 +1206,7 @@ class MessageLookup extends MessageLookupByLibrary { "scanThisBarcodeWithnyourAuthenticatorApp": MessageLookupByLibrary.simpleMessage( "Scan deze barcode met\nje authenticator app"), + "search": MessageLookupByLibrary.simpleMessage("Search"), "searchAlbumsEmptySection": MessageLookupByLibrary.simpleMessage("Albums"), "searchByAlbumNameHint": diff --git a/mobile/lib/generated/intl/messages_no.dart b/mobile/lib/generated/intl/messages_no.dart index 294292a3d4..0e5bd97b21 100644 --- a/mobile/lib/generated/intl/messages_no.dart +++ b/mobile/lib/generated/intl/messages_no.dart @@ -77,6 +77,7 @@ class MessageLookup extends MessageLookupByLibrary { "Modify your query, or try searching for"), "moveToHiddenAlbum": MessageLookupByLibrary.simpleMessage("Move to hidden album"), + "search": MessageLookupByLibrary.simpleMessage("Search"), "selectALocation": MessageLookupByLibrary.simpleMessage("Select a location"), "selectALocationFirst": diff --git a/mobile/lib/generated/intl/messages_pl.dart b/mobile/lib/generated/intl/messages_pl.dart index fea153d71b..b3a922b0ae 100644 --- a/mobile/lib/generated/intl/messages_pl.dart +++ b/mobile/lib/generated/intl/messages_pl.dart @@ -171,6 +171,7 @@ class MessageLookup extends MessageLookupByLibrary { "resetPasswordTitle": MessageLookupByLibrary.simpleMessage("Zresetuj hasło"), "saveKey": MessageLookupByLibrary.simpleMessage("Zapisz klucz"), + "search": MessageLookupByLibrary.simpleMessage("Search"), "selectALocation": MessageLookupByLibrary.simpleMessage("Select a location"), "selectALocationFirst": diff --git a/mobile/lib/generated/intl/messages_pt.dart b/mobile/lib/generated/intl/messages_pt.dart index 3168451dff..0747cfa826 100644 --- a/mobile/lib/generated/intl/messages_pt.dart +++ b/mobile/lib/generated/intl/messages_pt.dart @@ -1217,6 +1217,7 @@ class MessageLookup extends MessageLookupByLibrary { "scanThisBarcodeWithnyourAuthenticatorApp": MessageLookupByLibrary.simpleMessage( "Escaneie este código de barras com\nseu aplicativo autenticador"), + "search": MessageLookupByLibrary.simpleMessage("Search"), "searchAlbumsEmptySection": MessageLookupByLibrary.simpleMessage("Álbuns"), "searchByAlbumNameHint": diff --git a/mobile/lib/generated/intl/messages_zh.dart b/mobile/lib/generated/intl/messages_zh.dart index 73d2ae0f5e..7f4c0accf8 100644 --- a/mobile/lib/generated/intl/messages_zh.dart +++ b/mobile/lib/generated/intl/messages_zh.dart @@ -988,6 +988,7 @@ class MessageLookup extends MessageLookupByLibrary { "scanCode": MessageLookupByLibrary.simpleMessage("扫描二维码/条码"), "scanThisBarcodeWithnyourAuthenticatorApp": MessageLookupByLibrary.simpleMessage("用您的身份验证器应用\n扫描此条码"), + "search": MessageLookupByLibrary.simpleMessage("Search"), "searchAlbumsEmptySection": MessageLookupByLibrary.simpleMessage("相册"), "searchByAlbumNameHint": MessageLookupByLibrary.simpleMessage("相册名称"), "searchByExamples": MessageLookupByLibrary.simpleMessage( diff --git a/mobile/lib/generated/l10n.dart b/mobile/lib/generated/l10n.dart index 89b71a76a9..3fa9c2209a 100644 --- a/mobile/lib/generated/l10n.dart +++ b/mobile/lib/generated/l10n.dart @@ -8553,6 +8553,16 @@ class S { args: [], ); } + + /// `Search` + String get search { + return Intl.message( + 'Search', + name: 'search', + desc: '', + args: [], + ); + } } class AppLocalizationDelegate extends LocalizationsDelegate { diff --git a/mobile/lib/l10n/intl_cs.arb b/mobile/lib/l10n/intl_cs.arb index 6b7a4933bc..e7d3747252 100644 --- a/mobile/lib/l10n/intl_cs.arb +++ b/mobile/lib/l10n/intl_cs.arb @@ -17,5 +17,6 @@ "addViewers": "{count, plural, zero {Add viewer} one {Add viewer} other {Add viewers}}", "addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}", "longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption.", - "createCollaborativeLink": "Create collaborative link" + "createCollaborativeLink": "Create collaborative link", + "search": "Search" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_de.arb b/mobile/lib/l10n/intl_de.arb index 8bb844df3f..0e5807e1e8 100644 --- a/mobile/lib/l10n/intl_de.arb +++ b/mobile/lib/l10n/intl_de.arb @@ -1203,5 +1203,6 @@ "addViewers": "{count, plural, zero {Add viewer} one {Add viewer} other {Add viewers}}", "addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}", "longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption.", - "createCollaborativeLink": "Create collaborative link" + "createCollaborativeLink": "Create collaborative link", + "search": "Search" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_en.arb b/mobile/lib/l10n/intl_en.arb index 9d1c7bcf92..7115c69508 100644 --- a/mobile/lib/l10n/intl_en.arb +++ b/mobile/lib/l10n/intl_en.arb @@ -1211,5 +1211,6 @@ "invalidEndpointMessage": "Sorry, the endpoint you entered is invalid. Please enter a valid endpoint and try again.", "endpointUpdatedMessage": "Endpoint updated successfully", "customEndpoint": "Connected to {endpoint}", - "createCollaborativeLink": "Create collaborative link" + "createCollaborativeLink": "Create collaborative link", + "search": "Search" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_es.arb b/mobile/lib/l10n/intl_es.arb index 7dff210367..6515371fa5 100644 --- a/mobile/lib/l10n/intl_es.arb +++ b/mobile/lib/l10n/intl_es.arb @@ -979,5 +979,6 @@ "addViewers": "{count, plural, zero {Add viewer} one {Add viewer} other {Add viewers}}", "addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}", "longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption.", - "createCollaborativeLink": "Create collaborative link" + "createCollaborativeLink": "Create collaborative link", + "search": "Search" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_fr.arb b/mobile/lib/l10n/intl_fr.arb index d44d093c1c..1d8e5f6d3a 100644 --- a/mobile/lib/l10n/intl_fr.arb +++ b/mobile/lib/l10n/intl_fr.arb @@ -1160,5 +1160,6 @@ "addViewers": "{count, plural, zero {Add viewer} one {Add viewer} other {Add viewers}}", "addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}", "longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption.", - "createCollaborativeLink": "Create collaborative link" + "createCollaborativeLink": "Create collaborative link", + "search": "Search" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_it.arb b/mobile/lib/l10n/intl_it.arb index 9e884ed9e4..c9655dd065 100644 --- a/mobile/lib/l10n/intl_it.arb +++ b/mobile/lib/l10n/intl_it.arb @@ -1122,5 +1122,6 @@ "addViewers": "{count, plural, zero {Add viewer} one {Add viewer} other {Add viewers}}", "addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}", "longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption.", - "createCollaborativeLink": "Create collaborative link" + "createCollaborativeLink": "Create collaborative link", + "search": "Search" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_ko.arb b/mobile/lib/l10n/intl_ko.arb index 6b7a4933bc..e7d3747252 100644 --- a/mobile/lib/l10n/intl_ko.arb +++ b/mobile/lib/l10n/intl_ko.arb @@ -17,5 +17,6 @@ "addViewers": "{count, plural, zero {Add viewer} one {Add viewer} other {Add viewers}}", "addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}", "longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption.", - "createCollaborativeLink": "Create collaborative link" + "createCollaborativeLink": "Create collaborative link", + "search": "Search" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_nl.arb b/mobile/lib/l10n/intl_nl.arb index 120e4a2071..98302c20c6 100644 --- a/mobile/lib/l10n/intl_nl.arb +++ b/mobile/lib/l10n/intl_nl.arb @@ -1198,5 +1198,6 @@ "addViewers": "{count, plural, zero {Add viewer} one {Add viewer} other {Add viewers}}", "addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}", "longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption.", - "createCollaborativeLink": "Create collaborative link" + "createCollaborativeLink": "Create collaborative link", + "search": "Search" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_no.arb b/mobile/lib/l10n/intl_no.arb index 0b777b3538..8908eadb01 100644 --- a/mobile/lib/l10n/intl_no.arb +++ b/mobile/lib/l10n/intl_no.arb @@ -31,5 +31,6 @@ "addViewers": "{count, plural, zero {Add viewer} one {Add viewer} other {Add viewers}}", "addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}", "longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption.", - "createCollaborativeLink": "Create collaborative link" + "createCollaborativeLink": "Create collaborative link", + "search": "Search" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_pl.arb b/mobile/lib/l10n/intl_pl.arb index d358d4d2c4..13d740614d 100644 --- a/mobile/lib/l10n/intl_pl.arb +++ b/mobile/lib/l10n/intl_pl.arb @@ -118,5 +118,6 @@ "addViewers": "{count, plural, zero {Add viewer} one {Add viewer} other {Add viewers}}", "addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}", "longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption.", - "createCollaborativeLink": "Create collaborative link" + "createCollaborativeLink": "Create collaborative link", + "search": "Search" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_pt.arb b/mobile/lib/l10n/intl_pt.arb index 37b1041a9a..765ce3e1d3 100644 --- a/mobile/lib/l10n/intl_pt.arb +++ b/mobile/lib/l10n/intl_pt.arb @@ -1211,5 +1211,6 @@ "invalidEndpointMessage": "Desculpe, o endpoint que você inseriu é inválido. Por favor, insira um endpoint válido e tente novamente.", "endpointUpdatedMessage": "Endpoint atualizado com sucesso", "customEndpoint": "Conectado a {endpoint}", - "createCollaborativeLink": "Criar link colaborativo" + "createCollaborativeLink": "Criar link colaborativo", + "search": "Search" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_zh.arb b/mobile/lib/l10n/intl_zh.arb index 439643162a..4a991c7735 100644 --- a/mobile/lib/l10n/intl_zh.arb +++ b/mobile/lib/l10n/intl_zh.arb @@ -1211,5 +1211,6 @@ "invalidEndpointMessage": "抱歉,您输入的端点无效。请输入有效的端点,然后重试。", "endpointUpdatedMessage": "端点更新成功", "customEndpoint": "已连接至 {endpoint}", - "createCollaborativeLink": "创建协作链接" + "createCollaborativeLink": "创建协作链接", + "search": "Search" } \ No newline at end of file diff --git a/mobile/lib/ui/viewer/search/search_widget.dart b/mobile/lib/ui/viewer/search/search_widget.dart index 2beaa1ec19..1c6c7b693f 100644 --- a/mobile/lib/ui/viewer/search/search_widget.dart +++ b/mobile/lib/ui/viewer/search/search_widget.dart @@ -5,6 +5,7 @@ import "package:flutter/scheduler.dart"; import "package:photos/core/event_bus.dart"; import "package:photos/events/clear_and_unfocus_search_bar_event.dart"; import "package:photos/events/tab_changed_event.dart"; +import "package:photos/generated/l10n.dart"; import "package:photos/models/search/index_of_indexed_stack.dart"; import "package:photos/models/search/search_result.dart"; import "package:photos/services/search_service.dart"; @@ -130,17 +131,14 @@ class SearchWidgetState extends State { color: colorScheme.backgroundBase, child: Container( color: colorScheme.fillFaint, - child: TextFormField( + child: TextField( controller: textController, focusNode: focusNode, style: Theme.of(context).textTheme.titleMedium, // Below parameters are to disable auto-suggestion - enableSuggestions: false, - autocorrect: false, // Above parameters are to disable auto-suggestion decoration: InputDecoration( - //TODO: Extract string - hintText: "Search", + hintText: S.of(context).search, filled: true, fillColor: getEnteColorScheme(context).fillFaint, border: const UnderlineInputBorder( @@ -161,6 +159,9 @@ class SearchWidgetState extends State { minHeight: 44, minWidth: 44, ), + contentPadding: const EdgeInsets.symmetric( + vertical: 8, + ), prefixIcon: Hero( tag: "search_icon", child: Icon( @@ -168,6 +169,7 @@ class SearchWidgetState extends State { color: colorScheme.strokeFaint, ), ), + /*Using valueListenableBuilder inside a stateful widget because this widget is only rebuild when setState is called when deboucncing is over and the spinner needs to be shown while debouncing */ suffixIcon: ValueListenableBuilder( From f78e4d391423c3504e075e2d1ce0089458c53bbc Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 16 Apr 2024 19:39:36 +0530 Subject: [PATCH 77/84] Fix live photo cast --- .../components/Theatre/PhotoAuditorium.tsx | 95 ------------------- .../components/Theatre/VideoAuditorium.tsx | 55 ----------- .../cast/src/components/Theatre/index.tsx | 30 ------ web/apps/cast/src/pages/slideshow.tsx | 16 +--- 4 files changed, 4 insertions(+), 192 deletions(-) delete mode 100644 web/apps/cast/src/components/Theatre/PhotoAuditorium.tsx delete mode 100644 web/apps/cast/src/components/Theatre/VideoAuditorium.tsx delete mode 100644 web/apps/cast/src/components/Theatre/index.tsx diff --git a/web/apps/cast/src/components/Theatre/PhotoAuditorium.tsx b/web/apps/cast/src/components/Theatre/PhotoAuditorium.tsx deleted file mode 100644 index 0042dfe953..0000000000 --- a/web/apps/cast/src/components/Theatre/PhotoAuditorium.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import { SlideshowContext } from "pages/slideshow"; -import { useContext, useEffect, useState } from "react"; - -export default function PhotoAuditorium({ - url, - nextSlideUrl, -}: { - url: string; - nextSlideUrl: string; -}) { - const { showNextSlide } = useContext(SlideshowContext); - - const [showPreloadedNextSlide, setShowPreloadedNextSlide] = useState(false); - const [nextSlidePrerendered, setNextSlidePrerendered] = useState(false); - const [prerenderTime, setPrerenderTime] = useState(null); - - useEffect(() => { - let timeout: NodeJS.Timeout; - let timeout2: NodeJS.Timeout; - - if (nextSlidePrerendered) { - const elapsedTime = prerenderTime ? Date.now() - prerenderTime : 0; - const delayTime = Math.max(10000 - elapsedTime, 0); - - if (elapsedTime >= 10000) { - setShowPreloadedNextSlide(true); - } else { - timeout = setTimeout(() => { - setShowPreloadedNextSlide(true); - }, delayTime); - } - - if (showNextSlide) { - timeout2 = setTimeout(() => { - showNextSlide(); - setNextSlidePrerendered(false); - setPrerenderTime(null); - setShowPreloadedNextSlide(false); - }, delayTime); - } - } - - return () => { - if (timeout) clearTimeout(timeout); - if (timeout2) clearTimeout(timeout2); - }; - }, [nextSlidePrerendered, showNextSlide, prerenderTime]); - - return ( -
-
- - { - setNextSlidePrerendered(true); - setPrerenderTime(Date.now()); - }} - /> -
-
- ); -} diff --git a/web/apps/cast/src/components/Theatre/VideoAuditorium.tsx b/web/apps/cast/src/components/Theatre/VideoAuditorium.tsx deleted file mode 100644 index 2bf5ed4908..0000000000 --- a/web/apps/cast/src/components/Theatre/VideoAuditorium.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import mime from "mime-types"; -import { SlideshowContext } from "pages/slideshow"; -import { useContext, useEffect, useRef } from "react"; - -export default function VideoAuditorium({ - name, - url, -}: { - name: string; - url: string; -}) { - const { showNextSlide } = useContext(SlideshowContext); - - const videoRef = useRef(null); - - useEffect(() => { - attemptPlay(); - }, [url, videoRef]); - - const attemptPlay = async () => { - if (videoRef.current) { - try { - await videoRef.current.play(); - } catch { - showNextSlide(); - } - } - }; - - return ( -
- -
- ); -} diff --git a/web/apps/cast/src/components/Theatre/index.tsx b/web/apps/cast/src/components/Theatre/index.tsx deleted file mode 100644 index f7cac9c544..0000000000 --- a/web/apps/cast/src/components/Theatre/index.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { FILE_TYPE } from "constants/file"; -import PhotoAuditorium from "./PhotoAuditorium"; -// import VideoAuditorium from './VideoAuditorium'; - -interface fileProp { - fileName: string; - fileURL: string; - type: FILE_TYPE; -} - -interface IProps { - file1: fileProp; - file2: fileProp; -} - -export default function Theatre(props: IProps) { - switch (props.file1.type && props.file2.type) { - case FILE_TYPE.IMAGE: - return ( - - ); - // case FILE_TYPE.VIDEO: - // return ( - // - // ); - } -} diff --git a/web/apps/cast/src/pages/slideshow.tsx b/web/apps/cast/src/pages/slideshow.tsx index 692e611549..60aded0336 100644 --- a/web/apps/cast/src/pages/slideshow.tsx +++ b/web/apps/cast/src/pages/slideshow.tsx @@ -1,6 +1,6 @@ import log from "@/next/log"; import PairedSuccessfullyOverlay from "components/PairedSuccessfullyOverlay"; -import Theatre from "components/Theatre"; +import PhotoAuditorium from "components/PhotoAuditorium"; import { FILE_TYPE } from "constants/file"; import { useRouter } from "next/router"; import { createContext, useEffect, useState } from "react"; @@ -171,17 +171,9 @@ export default function Slideshow() { return ( <> - {loading && } From 2bb3e152f8329b07e0abd2c879da6d748ae62366 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 16 Apr 2024 19:54:00 +0530 Subject: [PATCH 78/84] Precache --- web/apps/cast/src/pages/slideshow.tsx | 28 ++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/web/apps/cast/src/pages/slideshow.tsx b/web/apps/cast/src/pages/slideshow.tsx index 60aded0336..8d8b61c703 100644 --- a/web/apps/cast/src/pages/slideshow.tsx +++ b/web/apps/cast/src/pages/slideshow.tsx @@ -162,12 +162,34 @@ export default function Slideshow() { } }; - useEffect(() => { - if (currentFile) { - getRenderableFileURL(); + const precacheNextRenderableFileURL = async () => { + if (!nextFile) return; + + const cacheValue = renderableFileURLCache.get(nextFile.id); + if (cacheValue) return; + + try { + const blob = await getPreviewableImage( + nextFile as EnteFile, + castToken, + ); + + const url = URL.createObjectURL(blob); + + renderableFileURLCache.set(nextFile?.id, url); + } catch (e) { + return; } + }; + + useEffect(() => { + getRenderableFileURL(); }, [currentFile]); + useEffect(() => { + precacheNextRenderableFileURL(); + }, [nextFile]); + return ( <> From 138b775c133839966d96141fc5f24ad448facac4 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 16 Apr 2024 19:57:08 +0530 Subject: [PATCH 79/84] At a more opportune place --- web/apps/cast/src/pages/slideshow.tsx | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/web/apps/cast/src/pages/slideshow.tsx b/web/apps/cast/src/pages/slideshow.tsx index 8d8b61c703..f26d3a5851 100644 --- a/web/apps/cast/src/pages/slideshow.tsx +++ b/web/apps/cast/src/pages/slideshow.tsx @@ -130,6 +130,7 @@ export default function Slideshow() { setCurrentFile(nextFile); setNextFile(nextNextFile); + precacheRenderableFileURL(nextNextFile); }; const [renderableFileURL, setRenderableFileURL] = useState(""); @@ -162,21 +163,12 @@ export default function Slideshow() { } }; - const precacheNextRenderableFileURL = async () => { - if (!nextFile) return; - - const cacheValue = renderableFileURLCache.get(nextFile.id); - if (cacheValue) return; - + const precacheRenderableFileURL = async (file: EnteFile) => { + if (renderableFileURLCache.get(file.id)) return; try { - const blob = await getPreviewableImage( - nextFile as EnteFile, - castToken, - ); - + const blob = await getPreviewableImage(file as EnteFile, castToken); const url = URL.createObjectURL(blob); - - renderableFileURLCache.set(nextFile?.id, url); + renderableFileURLCache.set(file?.id, url); } catch (e) { return; } @@ -186,10 +178,6 @@ export default function Slideshow() { getRenderableFileURL(); }, [currentFile]); - useEffect(() => { - precacheNextRenderableFileURL(); - }, [nextFile]); - return ( <> From 598a885df2d8bedfe36890e376535ac405db5f9a Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 16 Apr 2024 20:17:28 +0530 Subject: [PATCH 80/84] Refactor This doesn't fix the initial gap, functionality is still the same, but the flow is now easier to understand. --- web/apps/cast/src/pages/slideshow.tsx | 90 ++++++++++----------------- 1 file changed, 34 insertions(+), 56 deletions(-) diff --git a/web/apps/cast/src/pages/slideshow.tsx b/web/apps/cast/src/pages/slideshow.tsx index f26d3a5851..28061d0a47 100644 --- a/web/apps/cast/src/pages/slideshow.tsx +++ b/web/apps/cast/src/pages/slideshow.tsx @@ -20,18 +20,17 @@ export const SlideshowContext = createContext<{ const renderableFileURLCache = new Map(); export default function Slideshow() { - const [collectionFiles, setCollectionFiles] = useState([]); - - const [currentFile, setCurrentFile] = useState( - undefined, - ); - const [nextFile, setNextFile] = useState(undefined); - const [loading, setLoading] = useState(true); const [castToken, setCastToken] = useState(""); const [castCollection, setCastCollection] = useState< Collection | undefined >(undefined); + const [collectionFiles, setCollectionFiles] = useState([]); + const [currentFileId, setCurrentFileId] = useState(); + const [currentFileURL, setCurrentFileURL] = useState(); + const [nextFileURL, setNextFileURL] = useState(); + + const router = useRouter(); const syncCastFiles = async (token: string) => { try { @@ -93,8 +92,6 @@ export default function Slideshow() { return true; }; - const router = useRouter(); - useEffect(() => { try { const castToken = window.localStorage.getItem("castToken"); @@ -117,9 +114,9 @@ export default function Slideshow() { showNextSlide(); }, [collectionFiles]); - const showNextSlide = () => { + const showNextSlide = async () => { const currentIndex = collectionFiles.findIndex( - (file) => file.id === currentFile?.id, + (file) => file.id === currentFileId, ); const nextIndex = (currentIndex + 1) % collectionFiles.length; @@ -128,62 +125,43 @@ export default function Slideshow() { const nextFile = collectionFiles[nextIndex]; const nextNextFile = collectionFiles[nextNextIndex]; - setCurrentFile(nextFile); - setNextFile(nextNextFile); - precacheRenderableFileURL(nextNextFile); - }; + let nextURL = renderableFileURLCache.get(nextFile.id); + let nextNextURL = renderableFileURLCache.get(nextNextFile.id); - const [renderableFileURL, setRenderableFileURL] = useState(""); - - const getRenderableFileURL = async () => { - if (!currentFile) return; - - const cacheValue = renderableFileURLCache.get(currentFile.id); - if (cacheValue) { - setRenderableFileURL(cacheValue); - setLoading(false); - return; + if (!nextURL) { + try { + const blob = await getPreviewableImage(nextFile, castToken); + const url = URL.createObjectURL(blob); + renderableFileURLCache.set(nextFile.id, url); + nextURL = url; + } catch (e) { + return; + } } - try { - const blob = await getPreviewableImage( - currentFile as EnteFile, - castToken, - ); - - const url = URL.createObjectURL(blob); - - renderableFileURLCache.set(currentFile?.id, url); - - setRenderableFileURL(url); - } catch (e) { - return; - } finally { - setLoading(false); + if (!nextNextURL) { + try { + const blob = await getPreviewableImage(nextNextFile, castToken); + const url = URL.createObjectURL(blob); + renderableFileURLCache.set(nextNextFile.id, url); + nextNextURL = url; + } catch (e) { + return; + } } - }; - const precacheRenderableFileURL = async (file: EnteFile) => { - if (renderableFileURLCache.get(file.id)) return; - try { - const blob = await getPreviewableImage(file as EnteFile, castToken); - const url = URL.createObjectURL(blob); - renderableFileURLCache.set(file?.id, url); - } catch (e) { - return; - } + setLoading(false); + setCurrentFileId(nextFile.id); + setCurrentFileURL(nextURL); + setNextFileURL(nextNextURL); }; - useEffect(() => { - getRenderableFileURL(); - }, [currentFile]); - return ( <> {loading && } From 0a248e5ce5e0f4c92acc0db7be60feec1d693f23 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 16 Apr 2024 20:22:12 +0530 Subject: [PATCH 81/84] Prepare --- .../cast/src/components/PhotoAuditorium.tsx | 20 +++++++-------- web/apps/cast/src/pages/slideshow.tsx | 25 ++++++++----------- 2 files changed, 20 insertions(+), 25 deletions(-) diff --git a/web/apps/cast/src/components/PhotoAuditorium.tsx b/web/apps/cast/src/components/PhotoAuditorium.tsx index 0042dfe953..9f0d9120d9 100644 --- a/web/apps/cast/src/components/PhotoAuditorium.tsx +++ b/web/apps/cast/src/components/PhotoAuditorium.tsx @@ -1,15 +1,15 @@ -import { SlideshowContext } from "pages/slideshow"; -import { useContext, useEffect, useState } from "react"; +import { useEffect, useState } from "react"; -export default function PhotoAuditorium({ - url, - nextSlideUrl, -}: { +interface PhotoAuditoriumProps { url: string; nextSlideUrl: string; -}) { - const { showNextSlide } = useContext(SlideshowContext); - + showNextSlide: () => void; +} +export const PhotoAuditorium: React.FC = ({ + url, + nextSlideUrl, + showNextSlide, +}) => { const [showPreloadedNextSlide, setShowPreloadedNextSlide] = useState(false); const [nextSlidePrerendered, setNextSlidePrerendered] = useState(false); const [prerenderTime, setPrerenderTime] = useState(null); @@ -92,4 +92,4 @@ export default function PhotoAuditorium({ ); -} +}; diff --git a/web/apps/cast/src/pages/slideshow.tsx b/web/apps/cast/src/pages/slideshow.tsx index 28061d0a47..2530159815 100644 --- a/web/apps/cast/src/pages/slideshow.tsx +++ b/web/apps/cast/src/pages/slideshow.tsx @@ -1,9 +1,9 @@ import log from "@/next/log"; import PairedSuccessfullyOverlay from "components/PairedSuccessfullyOverlay"; -import PhotoAuditorium from "components/PhotoAuditorium"; +import { PhotoAuditorium } from "components/PhotoAuditorium"; import { FILE_TYPE } from "constants/file"; import { useRouter } from "next/router"; -import { createContext, useEffect, useState } from "react"; +import { useEffect, useState } from "react"; import { getCastCollection, getLocalFiles, @@ -13,10 +13,6 @@ import { Collection } from "types/collection"; import { EnteFile } from "types/file"; import { getPreviewableImage, isRawFileFromFileName } from "utils/file"; -export const SlideshowContext = createContext<{ - showNextSlide: () => void; -}>(null); - const renderableFileURLCache = new Map(); export default function Slideshow() { @@ -28,6 +24,7 @@ export default function Slideshow() { const [collectionFiles, setCollectionFiles] = useState([]); const [currentFileId, setCurrentFileId] = useState(); const [currentFileURL, setCurrentFileURL] = useState(); + // eslint-disable-next-line @typescript-eslint/no-unused-vars const [nextFileURL, setNextFileURL] = useState(); const router = useRouter(); @@ -156,15 +153,13 @@ export default function Slideshow() { setNextFileURL(nextNextURL); }; + if (loading) return ; + return ( - <> - - - - {loading && } - + ); } From 2dd705d7f7140650d1c448ea7dcb3f823fe2852c Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 16 Apr 2024 20:49:47 +0530 Subject: [PATCH 82/84] Not better not worse --- .../cast/src/components/PhotoAuditorium.tsx | 57 +++++-------------- web/apps/cast/src/pages/slideshow.tsx | 3 +- 2 files changed, 14 insertions(+), 46 deletions(-) diff --git a/web/apps/cast/src/components/PhotoAuditorium.tsx b/web/apps/cast/src/components/PhotoAuditorium.tsx index 9f0d9120d9..6aa2c3990b 100644 --- a/web/apps/cast/src/components/PhotoAuditorium.tsx +++ b/web/apps/cast/src/components/PhotoAuditorium.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from "react"; +import { useEffect } from "react"; interface PhotoAuditoriumProps { url: string; @@ -10,41 +10,15 @@ export const PhotoAuditorium: React.FC = ({ nextSlideUrl, showNextSlide, }) => { - const [showPreloadedNextSlide, setShowPreloadedNextSlide] = useState(false); - const [nextSlidePrerendered, setNextSlidePrerendered] = useState(false); - const [prerenderTime, setPrerenderTime] = useState(null); - useEffect(() => { - let timeout: NodeJS.Timeout; - let timeout2: NodeJS.Timeout; - - if (nextSlidePrerendered) { - const elapsedTime = prerenderTime ? Date.now() - prerenderTime : 0; - const delayTime = Math.max(10000 - elapsedTime, 0); - - if (elapsedTime >= 10000) { - setShowPreloadedNextSlide(true); - } else { - timeout = setTimeout(() => { - setShowPreloadedNextSlide(true); - }, delayTime); - } - - if (showNextSlide) { - timeout2 = setTimeout(() => { - showNextSlide(); - setNextSlidePrerendered(false); - setPrerenderTime(null); - setShowPreloadedNextSlide(false); - }, delayTime); - } - } + const timeoutId = window.setTimeout(() => { + showNextSlide(); + }, 10000); return () => { - if (timeout) clearTimeout(timeout); - if (timeout2) clearTimeout(timeout2); + if (timeoutId) clearTimeout(timeoutId); }; - }, [nextSlidePrerendered, showNextSlide, prerenderTime]); + }, [showNextSlide]); return (
= ({ backdropFilter: "blur(10px)", }} > - { - setNextSlidePrerendered(true); - setPrerenderTime(Date.now()); + /> +
diff --git a/web/apps/cast/src/pages/slideshow.tsx b/web/apps/cast/src/pages/slideshow.tsx index 2530159815..3a98efbf5e 100644 --- a/web/apps/cast/src/pages/slideshow.tsx +++ b/web/apps/cast/src/pages/slideshow.tsx @@ -24,7 +24,6 @@ export default function Slideshow() { const [collectionFiles, setCollectionFiles] = useState([]); const [currentFileId, setCurrentFileId] = useState(); const [currentFileURL, setCurrentFileURL] = useState(); - // eslint-disable-next-line @typescript-eslint/no-unused-vars const [nextFileURL, setNextFileURL] = useState(); const router = useRouter(); @@ -158,7 +157,7 @@ export default function Slideshow() { return ( ); From c98d5a3e4069026d2803a181d7fc3afbeeb58f79 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 16 Apr 2024 20:59:27 +0530 Subject: [PATCH 83/84] Filter out files with HEIC previews --- web/apps/cast/src/pages/slideshow.tsx | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/web/apps/cast/src/pages/slideshow.tsx b/web/apps/cast/src/pages/slideshow.tsx index 3a98efbf5e..774bbd4da9 100644 --- a/web/apps/cast/src/pages/slideshow.tsx +++ b/web/apps/cast/src/pages/slideshow.tsx @@ -20,7 +20,7 @@ export default function Slideshow() { const [castToken, setCastToken] = useState(""); const [castCollection, setCastCollection] = useState< Collection | undefined - >(undefined); + >(); const [collectionFiles, setCollectionFiles] = useState([]); const [currentFileId, setCurrentFileId] = useState(); const [currentFileURL, setCurrentFileURL] = useState(); @@ -67,23 +67,12 @@ export default function Slideshow() { const isFileEligibleForCast = (file: EnteFile) => { const fileType = file.metadata.fileType; - if (fileType !== FILE_TYPE.IMAGE && fileType !== FILE_TYPE.LIVE_PHOTO) { + if (fileType !== FILE_TYPE.IMAGE && fileType !== FILE_TYPE.LIVE_PHOTO) return false; - } - const fileSizeLimit = 100 * 1024 * 1024; + if (file.info.fileSize > 100 * 1024 * 1024) return false; - if (file.info.fileSize > fileSizeLimit) { - return false; - } - - const name = file.metadata.title; - - if (fileType === FILE_TYPE.IMAGE) { - if (isRawFileFromFileName(name)) { - return false; - } - } + if (isRawFileFromFileName(file.metadata.title)) return false; return true; }; From d80358552f4a96259390801e4a6618ee5aa47c5c Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 16 Apr 2024 21:02:57 +0530 Subject: [PATCH 84/84] Trim spaces for more forgiving copy paste --- .../Collections/CollectionOptions/AlbumCastDialog.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/apps/photos/src/components/Collections/CollectionOptions/AlbumCastDialog.tsx b/web/apps/photos/src/components/Collections/CollectionOptions/AlbumCastDialog.tsx index 8a5cb2c909..fdabffe846 100644 --- a/web/apps/photos/src/components/Collections/CollectionOptions/AlbumCastDialog.tsx +++ b/web/apps/photos/src/components/Collections/CollectionOptions/AlbumCastDialog.tsx @@ -50,7 +50,7 @@ export default function AlbumCastDialog(props: Props) { setFieldError, ) => { try { - await doCast(value); + await doCast(value.trim()); props.onHide(); } catch (e) { const error = e as Error;