From 6e4db6c0dfb14ec282e78189a3ee7a1bf8859663 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Thu, 28 Mar 2024 14:57:19 +0530 Subject: [PATCH 01/70] 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/70] 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/70] 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/70] 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/70] 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/70] 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/70] 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/70] 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/70] 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/70] 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/70] 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 99d84821c745cdb547bc44d456e7a195aaff091e Mon Sep 17 00:00:00 2001 From: Prateek Sunal Date: Sat, 6 Apr 2024 21:24:14 +0530 Subject: [PATCH 12/70] feat: add multipart upload support --- mobile/lib/core/constants.dart | 10 + mobile/lib/utils/file_uploader.dart | 13 +- mobile/lib/utils/multipart_upload_util.dart | 255 ++++++++++++++++++++ mobile/pubspec.lock | 2 +- mobile/pubspec.yaml | 1 + 5 files changed, 278 insertions(+), 3 deletions(-) create mode 100644 mobile/lib/utils/multipart_upload_util.dart diff --git a/mobile/lib/core/constants.dart b/mobile/lib/core/constants.dart index 6f8f191154..640af728b3 100644 --- a/mobile/lib/core/constants.dart +++ b/mobile/lib/core/constants.dart @@ -1,3 +1,5 @@ +import "package:photos/utils/crypto_util.dart"; + const int thumbnailSmallSize = 256; const int thumbnailQuality = 50; const int thumbnailLargeSize = 512; @@ -45,6 +47,14 @@ class FFDefault { static const bool enablePasskey = false; } +// this is the chunk size of the un-encrypted file which is read and encrypted before uploading it as a single part. +const multipartPartSize = 20 * 1024 * 1024; + +const fileReaderChunkSize = encryptionChunkSize; + +final fileChunksCombinedForAUploadPart = + (multipartPartSize / fileReaderChunkSize).floor(); + const kDefaultProductionEndpoint = 'https://api.ente.io'; const int intMaxValue = 9223372036854775807; diff --git a/mobile/lib/utils/file_uploader.dart b/mobile/lib/utils/file_uploader.dart index 7c898f985e..df3e54aeca 100644 --- a/mobile/lib/utils/file_uploader.dart +++ b/mobile/lib/utils/file_uploader.dart @@ -37,6 +37,7 @@ import 'package:photos/utils/crypto_util.dart'; import 'package:photos/utils/file_download_util.dart'; import 'package:photos/utils/file_uploader_util.dart'; import "package:photos/utils/file_util.dart"; +import "package:photos/utils/multipart_upload_util.dart"; import 'package:shared_preferences/shared_preferences.dart'; import 'package:tuple/tuple.dart'; import "package:uuid/uuid.dart"; @@ -492,9 +493,17 @@ class FileUploader { final String thumbnailObjectKey = await _putFile(thumbnailUploadURL, encryptedThumbnailFile); - final fileUploadURL = await _getUploadURL(); - final String fileObjectKey = await _putFile(fileUploadURL, encryptedFile); + final count = await calculatePartCount( + await encryptedFile.length(), + ); + final fileUploadURLs = await getMultipartUploadURLs(count); + final fileObjectKey = fileUploadURLs.objectKey; + + await putMultipartFile(fileUploadURLs, encryptedFile); + + // final fileUploadURL = await _getUploadURL(); + // fileObjectKey = await _putFile(fileUploadURL, encryptedFile); final metadata = await file.getMetadataForUpload(mediaUploadData); final encryptedMetadataResult = await CryptoUtil.encryptChaCha( utf8.encode(jsonEncode(metadata)) as Uint8List, diff --git a/mobile/lib/utils/multipart_upload_util.dart b/mobile/lib/utils/multipart_upload_util.dart new file mode 100644 index 0000000000..18c3f4795b --- /dev/null +++ b/mobile/lib/utils/multipart_upload_util.dart @@ -0,0 +1,255 @@ +// ignore_for_file: implementation_imports + +import "dart:io"; + +import "package:dio/dio.dart"; +import "package:logging/logging.dart"; +import "package:photos/core/constants.dart"; +import "package:photos/core/network/network.dart"; +import "package:xml/src/xml/entities/named_entities.dart"; +import "package:xml/xml.dart"; + +final _enteDio = NetworkClient.instance.enteDio; +final _dio = NetworkClient.instance.getDio(); + +class MultipartUploadURLs { + final String objectKey; + final List partsURLs; + final String completeURL; + + MultipartUploadURLs({ + required this.objectKey, + required this.partsURLs, + required this.completeURL, + }); + + factory MultipartUploadURLs.fromMap(Map map) { + return MultipartUploadURLs( + objectKey: map["urls"]["objectKey"], + partsURLs: (map["urls"]["partURLs"] as List).cast(), + completeURL: map["urls"]["completeURL"], + ); + } +} + +Future calculatePartCount(int fileSize) async { + final partCount = (fileSize / multipartPartSize).ceil(); + return partCount; +} + +Future getMultipartUploadURLs(int count) async { + try { + final response = await _enteDio.get( + "/files/multipart-upload-urls", + queryParameters: { + "count": count, + }, + ); + + return MultipartUploadURLs.fromMap(response.data); + } on Exception catch (e) { + Logger("MultipartUploadURL").severe(e); + rethrow; + } +} + +Future putMultipartFile( + MultipartUploadURLs urls, + File encryptedFile, +) async { + // upload individual parts and get their etags + final etags = await uploadParts(urls.partsURLs, encryptedFile); + + print(etags); + + // complete the multipart upload + await completeMultipartUpload(etags, urls.completeURL); +} + +Future> uploadParts( + List partsURLs, + File encryptedFile, +) async { + final partsLength = partsURLs.length; + final etags = {}; + + for (int i = 0; i < partsLength; i++) { + final partURL = partsURLs[i]; + final isLastPart = i == partsLength - 1; + final fileSize = isLastPart + ? encryptedFile.lengthSync() % multipartPartSize + : multipartPartSize; + + final response = await _dio.put( + partURL, + data: encryptedFile.openRead( + i * multipartPartSize, + isLastPart ? null : multipartPartSize, + ), + options: Options( + headers: { + Headers.contentLengthHeader: fileSize, + }, + ), + ); + + final eTag = response.headers.value("etag"); + + if (eTag?.isEmpty ?? true) { + throw Exception('ETAG_MISSING'); + } + + etags[i] = eTag!; + } + + return etags; +} + +Future completeMultipartUpload( + Map partEtags, + String completeURL, +) async { + final body = convertJs2Xml({ + 'CompleteMultipartUpload': partEtags.entries.toList(), + }); + + print(body); + + try { + await _dio.post( + completeURL, + data: body, + options: Options( + contentType: "text/xml", + ), + ); + } catch (e) { + Logger("MultipartUpload").severe(e); + rethrow; + } +} + +// for converting the response to xml +String convertJs2Xml(Map json) { + final builder = XmlBuilder(); + buildXml(builder, json); + return builder.buildDocument().toXmlString( + pretty: true, + indent: ' ', + entityMapping: defaultMyEntityMapping, + ); +} + +void buildXml(XmlBuilder builder, dynamic node) { + if (node is Map) { + node.forEach((key, value) { + builder.element(key, nest: () => buildXml(builder, value)); + }); + } else if (node is List) { + for (var item in node) { + buildXml(builder, item); + } + } else { + builder.element( + "Part", + nest: () { + builder.attribute( + "PartNumber", + (node as MapEntry).key + 1, + ); + print(node.value); + builder.attribute("ETag", node.value); + }, + ); + } +} + +XmlEntityMapping defaultMyEntityMapping = MyXmlDefaultEntityMapping.xml(); + +class MyXmlDefaultEntityMapping extends XmlDefaultEntityMapping { + MyXmlDefaultEntityMapping.xml() : this(xmlEntities); + MyXmlDefaultEntityMapping.html() : this(htmlEntities); + MyXmlDefaultEntityMapping.html5() : this(html5Entities); + MyXmlDefaultEntityMapping(super.entities); + + @override + String encodeText(String input) => + input.replaceAllMapped(_textPattern, _textReplace); + + @override + String encodeAttributeValue(String input, XmlAttributeType type) { + switch (type) { + case XmlAttributeType.SINGLE_QUOTE: + return input.replaceAllMapped( + _singeQuoteAttributePattern, + _singeQuoteAttributeReplace, + ); + case XmlAttributeType.DOUBLE_QUOTE: + return input.replaceAllMapped( + _doubleQuoteAttributePattern, + _doubleQuoteAttributeReplace, + ); + } + } +} + +final _textPattern = RegExp(r'[&<>' + _highlyDiscouragedCharClass + r']'); + +String _textReplace(Match match) { + final toEscape = match.group(0)!; + switch (toEscape) { + case '<': + return '<'; + case '&': + return '&'; + case '>': + return '>'; + default: + return _asNumericCharacterReferences(toEscape); + } +} + +final _singeQuoteAttributePattern = + RegExp(r"['&<>\n\r\t" + _highlyDiscouragedCharClass + r']'); + +String _singeQuoteAttributeReplace(Match match) { + final toEscape = match.group(0)!; + switch (toEscape) { + case "'": + return ''; + case '&': + return '&'; + case '<': + return '<'; + case '>': + return '>'; + default: + return _asNumericCharacterReferences(toEscape); + } +} + +final _doubleQuoteAttributePattern = + RegExp(r'["&<>\n\r\t' + _highlyDiscouragedCharClass + r']'); + +String _doubleQuoteAttributeReplace(Match match) { + final toEscape = match.group(0)!; + switch (toEscape) { + case '"': + return ''; + case '&': + return '&'; + case '<': + return '<'; + case '>': + return '>'; + default: + return _asNumericCharacterReferences(toEscape); + } +} + +const _highlyDiscouragedCharClass = + r'\u0001-\u0008\u000b\u000c\u000e-\u001f\u007f-\u0084\u0086-\u009f'; + +String _asNumericCharacterReferences(String toEscape) => toEscape.runes + .map((rune) => '&#x${rune.toRadixString(16).toUpperCase()};') + .join(); diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index cb89d90d7f..a53c6b680a 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -2505,7 +2505,7 @@ packages: source: hosted version: "0.2.0+3" xml: - dependency: transitive + dependency: "direct main" description: name: xml sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index d4a85ec982..a3b821a814 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -172,6 +172,7 @@ dependencies: wallpaper_manager_flutter: ^0.0.2 wechat_assets_picker: ^8.6.3 widgets_to_image: ^0.0.2 + xml: ^6.3.0 dependency_overrides: # current fork of tfite_flutter_helper depends on ffi: ^1.x.x From 69394fc8a63d1bac7e4d9af1a13e86255e99f6bc Mon Sep 17 00:00:00 2001 From: Prateek Sunal Date: Sat, 6 Apr 2024 21:30:44 +0530 Subject: [PATCH 13/70] fix: separate xml parser util --- mobile/lib/utils/multipart_upload_util.dart | 128 +------------------- mobile/lib/utils/xml_parser_util.dart | 128 ++++++++++++++++++++ 2 files changed, 129 insertions(+), 127 deletions(-) create mode 100644 mobile/lib/utils/xml_parser_util.dart diff --git a/mobile/lib/utils/multipart_upload_util.dart b/mobile/lib/utils/multipart_upload_util.dart index 18c3f4795b..f2d7b4b49a 100644 --- a/mobile/lib/utils/multipart_upload_util.dart +++ b/mobile/lib/utils/multipart_upload_util.dart @@ -6,8 +6,7 @@ import "package:dio/dio.dart"; import "package:logging/logging.dart"; import "package:photos/core/constants.dart"; import "package:photos/core/network/network.dart"; -import "package:xml/src/xml/entities/named_entities.dart"; -import "package:xml/xml.dart"; +import "package:photos/utils/xml_parser_util.dart"; final _enteDio = NetworkClient.instance.enteDio; final _dio = NetworkClient.instance.getDio(); @@ -128,128 +127,3 @@ Future completeMultipartUpload( rethrow; } } - -// for converting the response to xml -String convertJs2Xml(Map json) { - final builder = XmlBuilder(); - buildXml(builder, json); - return builder.buildDocument().toXmlString( - pretty: true, - indent: ' ', - entityMapping: defaultMyEntityMapping, - ); -} - -void buildXml(XmlBuilder builder, dynamic node) { - if (node is Map) { - node.forEach((key, value) { - builder.element(key, nest: () => buildXml(builder, value)); - }); - } else if (node is List) { - for (var item in node) { - buildXml(builder, item); - } - } else { - builder.element( - "Part", - nest: () { - builder.attribute( - "PartNumber", - (node as MapEntry).key + 1, - ); - print(node.value); - builder.attribute("ETag", node.value); - }, - ); - } -} - -XmlEntityMapping defaultMyEntityMapping = MyXmlDefaultEntityMapping.xml(); - -class MyXmlDefaultEntityMapping extends XmlDefaultEntityMapping { - MyXmlDefaultEntityMapping.xml() : this(xmlEntities); - MyXmlDefaultEntityMapping.html() : this(htmlEntities); - MyXmlDefaultEntityMapping.html5() : this(html5Entities); - MyXmlDefaultEntityMapping(super.entities); - - @override - String encodeText(String input) => - input.replaceAllMapped(_textPattern, _textReplace); - - @override - String encodeAttributeValue(String input, XmlAttributeType type) { - switch (type) { - case XmlAttributeType.SINGLE_QUOTE: - return input.replaceAllMapped( - _singeQuoteAttributePattern, - _singeQuoteAttributeReplace, - ); - case XmlAttributeType.DOUBLE_QUOTE: - return input.replaceAllMapped( - _doubleQuoteAttributePattern, - _doubleQuoteAttributeReplace, - ); - } - } -} - -final _textPattern = RegExp(r'[&<>' + _highlyDiscouragedCharClass + r']'); - -String _textReplace(Match match) { - final toEscape = match.group(0)!; - switch (toEscape) { - case '<': - return '<'; - case '&': - return '&'; - case '>': - return '>'; - default: - return _asNumericCharacterReferences(toEscape); - } -} - -final _singeQuoteAttributePattern = - RegExp(r"['&<>\n\r\t" + _highlyDiscouragedCharClass + r']'); - -String _singeQuoteAttributeReplace(Match match) { - final toEscape = match.group(0)!; - switch (toEscape) { - case "'": - return ''; - case '&': - return '&'; - case '<': - return '<'; - case '>': - return '>'; - default: - return _asNumericCharacterReferences(toEscape); - } -} - -final _doubleQuoteAttributePattern = - RegExp(r'["&<>\n\r\t' + _highlyDiscouragedCharClass + r']'); - -String _doubleQuoteAttributeReplace(Match match) { - final toEscape = match.group(0)!; - switch (toEscape) { - case '"': - return ''; - case '&': - return '&'; - case '<': - return '<'; - case '>': - return '>'; - default: - return _asNumericCharacterReferences(toEscape); - } -} - -const _highlyDiscouragedCharClass = - r'\u0001-\u0008\u000b\u000c\u000e-\u001f\u007f-\u0084\u0086-\u009f'; - -String _asNumericCharacterReferences(String toEscape) => toEscape.runes - .map((rune) => '&#x${rune.toRadixString(16).toUpperCase()};') - .join(); diff --git a/mobile/lib/utils/xml_parser_util.dart b/mobile/lib/utils/xml_parser_util.dart new file mode 100644 index 0000000000..eecfc7d22d --- /dev/null +++ b/mobile/lib/utils/xml_parser_util.dart @@ -0,0 +1,128 @@ +// ignore_for_file: implementation_imports + +import "package:xml/src/xml/entities/named_entities.dart"; +import "package:xml/xml.dart"; + +// for converting the response to xml +String convertJs2Xml(Map json) { + final builder = XmlBuilder(); + buildXml(builder, json); + return builder.buildDocument().toXmlString( + pretty: true, + indent: ' ', + entityMapping: defaultMyEntityMapping, + ); +} + +void buildXml(XmlBuilder builder, dynamic node) { + if (node is Map) { + node.forEach((key, value) { + builder.element(key, nest: () => buildXml(builder, value)); + }); + } else if (node is List) { + for (var item in node) { + buildXml(builder, item); + } + } else { + builder.element( + "Part", + nest: () { + builder.attribute( + "PartNumber", + (node as MapEntry).key + 1, + ); + builder.attribute("ETag", node.value); + }, + ); + } +} + +XmlEntityMapping defaultMyEntityMapping = MyXmlDefaultEntityMapping.xml(); + +class MyXmlDefaultEntityMapping extends XmlDefaultEntityMapping { + MyXmlDefaultEntityMapping.xml() : this(xmlEntities); + MyXmlDefaultEntityMapping.html() : this(htmlEntities); + MyXmlDefaultEntityMapping.html5() : this(html5Entities); + MyXmlDefaultEntityMapping(super.entities); + + @override + String encodeText(String input) => + input.replaceAllMapped(_textPattern, _textReplace); + + @override + String encodeAttributeValue(String input, XmlAttributeType type) { + switch (type) { + case XmlAttributeType.SINGLE_QUOTE: + return input.replaceAllMapped( + _singeQuoteAttributePattern, + _singeQuoteAttributeReplace, + ); + case XmlAttributeType.DOUBLE_QUOTE: + return input.replaceAllMapped( + _doubleQuoteAttributePattern, + _doubleQuoteAttributeReplace, + ); + } + } +} + +final _textPattern = RegExp(r'[&<>' + _highlyDiscouragedCharClass + r']'); + +String _textReplace(Match match) { + final toEscape = match.group(0)!; + switch (toEscape) { + case '<': + return '<'; + case '&': + return '&'; + case '>': + return '>'; + default: + return _asNumericCharacterReferences(toEscape); + } +} + +final _singeQuoteAttributePattern = + RegExp(r"['&<>\n\r\t" + _highlyDiscouragedCharClass + r']'); + +String _singeQuoteAttributeReplace(Match match) { + final toEscape = match.group(0)!; + switch (toEscape) { + case "'": + return ''; + case '&': + return '&'; + case '<': + return '<'; + case '>': + return '>'; + default: + return _asNumericCharacterReferences(toEscape); + } +} + +final _doubleQuoteAttributePattern = + RegExp(r'["&<>\n\r\t' + _highlyDiscouragedCharClass + r']'); + +String _doubleQuoteAttributeReplace(Match match) { + final toEscape = match.group(0)!; + switch (toEscape) { + case '"': + return ''; + case '&': + return '&'; + case '<': + return '<'; + case '>': + return '>'; + default: + return _asNumericCharacterReferences(toEscape); + } +} + +const _highlyDiscouragedCharClass = + r'\u0001-\u0008\u000b\u000c\u000e-\u001f\u007f-\u0084\u0086-\u009f'; + +String _asNumericCharacterReferences(String toEscape) => toEscape.runes + .map((rune) => '&#x${rune.toRadixString(16).toUpperCase()};') + .join(); From baeac733391da678859b188ace29bdd77e6568cb Mon Sep 17 00:00:00 2001 From: Prateek Sunal Date: Sat, 6 Apr 2024 22:42:57 +0530 Subject: [PATCH 14/70] fix: complete url xml --- mobile/lib/utils/multipart_upload_util.dart | 20 +++++++++++++++----- mobile/lib/utils/xml_parser_util.dart | 18 ++++++++++++++---- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/mobile/lib/utils/multipart_upload_util.dart b/mobile/lib/utils/multipart_upload_util.dart index f2d7b4b49a..fa3250baab 100644 --- a/mobile/lib/utils/multipart_upload_util.dart +++ b/mobile/lib/utils/multipart_upload_util.dart @@ -11,6 +11,13 @@ import "package:photos/utils/xml_parser_util.dart"; final _enteDio = NetworkClient.instance.enteDio; final _dio = NetworkClient.instance.getDio(); +class PartETag { + final int partNumber; + final String eTag; + + PartETag(this.partNumber, this.eTag); +} + class MultipartUploadURLs { final String objectKey; final List partsURLs; @@ -59,8 +66,6 @@ Future putMultipartFile( // upload individual parts and get their etags final etags = await uploadParts(urls.partsURLs, encryptedFile); - print(etags); - // complete the multipart upload await completeMultipartUpload(etags, urls.completeURL); } @@ -109,11 +114,16 @@ Future completeMultipartUpload( String completeURL, ) async { final body = convertJs2Xml({ - 'CompleteMultipartUpload': partEtags.entries.toList(), + 'CompleteMultipartUpload': partEtags.entries + .map( + (e) => PartETag( + e.key + 1, + e.value, + ), + ) + .toList(), }); - print(body); - try { await _dio.post( completeURL, diff --git a/mobile/lib/utils/xml_parser_util.dart b/mobile/lib/utils/xml_parser_util.dart index eecfc7d22d..dd825fb6d4 100644 --- a/mobile/lib/utils/xml_parser_util.dart +++ b/mobile/lib/utils/xml_parser_util.dart @@ -1,5 +1,6 @@ // ignore_for_file: implementation_imports +import "package:photos/utils/multipart_upload_util.dart"; import "package:xml/src/xml/entities/named_entities.dart"; import "package:xml/xml.dart"; @@ -23,17 +24,26 @@ void buildXml(XmlBuilder builder, dynamic node) { for (var item in node) { buildXml(builder, item); } - } else { + } else if (node is PartETag) { builder.element( "Part", nest: () { - builder.attribute( + builder.element( "PartNumber", - (node as MapEntry).key + 1, + nest: () { + buildXml(builder, node.partNumber); + }, + ); + builder.element( + "ETag", + nest: () { + buildXml(builder, node.eTag); + }, ); - builder.attribute("ETag", node.value); }, ); + } else { + builder.text(node.toString()); } } From 2b9db5cbfbcf613fea4c1ba98be7f7d7a368cf28 Mon Sep 17 00:00:00 2001 From: Prateek Sunal Date: Sun, 7 Apr 2024 12:09:59 +0530 Subject: [PATCH 15/70] fix: only multipart when count is greater than 1 --- mobile/lib/utils/file_uploader.dart | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/mobile/lib/utils/file_uploader.dart b/mobile/lib/utils/file_uploader.dart index df3e54aeca..c60ef3e861 100644 --- a/mobile/lib/utils/file_uploader.dart +++ b/mobile/lib/utils/file_uploader.dart @@ -497,13 +497,16 @@ class FileUploader { await encryptedFile.length(), ); - final fileUploadURLs = await getMultipartUploadURLs(count); - final fileObjectKey = fileUploadURLs.objectKey; + String fileObjectKey; - await putMultipartFile(fileUploadURLs, encryptedFile); + if (count <= 1) { + final fileUploadURL = await _getUploadURL(); + fileObjectKey = await _putFile(fileUploadURL, encryptedFile); + } else { + final fileUploadURLs = await getMultipartUploadURLs(count); + fileObjectKey = await putMultipartFile(fileUploadURLs, encryptedFile); + } - // final fileUploadURL = await _getUploadURL(); - // fileObjectKey = await _putFile(fileUploadURL, encryptedFile); final metadata = await file.getMetadataForUpload(mediaUploadData); final encryptedMetadataResult = await CryptoUtil.encryptChaCha( utf8.encode(jsonEncode(metadata)) as Uint8List, From 780ec7f9d6dc0ca73f269b940484235112449141 Mon Sep 17 00:00:00 2001 From: Prateek Sunal Date: Sun, 7 Apr 2024 12:10:20 +0530 Subject: [PATCH 16/70] fix: generalize xml parser logic --- mobile/lib/utils/multipart_upload_util.dart | 17 +++++++++++-- mobile/lib/utils/xml_parser_util.dart | 27 +++++++++------------ 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/mobile/lib/utils/multipart_upload_util.dart b/mobile/lib/utils/multipart_upload_util.dart index fa3250baab..fc4ac4860c 100644 --- a/mobile/lib/utils/multipart_upload_util.dart +++ b/mobile/lib/utils/multipart_upload_util.dart @@ -11,11 +11,22 @@ import "package:photos/utils/xml_parser_util.dart"; final _enteDio = NetworkClient.instance.enteDio; final _dio = NetworkClient.instance.getDio(); -class PartETag { +class PartETag extends XmlParsableObject { final int partNumber; final String eTag; PartETag(this.partNumber, this.eTag); + + @override + String get elementName => "Part"; + + @override + Map toMap() { + return { + "PartNumber": partNumber, + "ETag": eTag, + }; + } } class MultipartUploadURLs { @@ -59,7 +70,7 @@ Future getMultipartUploadURLs(int count) async { } } -Future putMultipartFile( +Future putMultipartFile( MultipartUploadURLs urls, File encryptedFile, ) async { @@ -68,6 +79,8 @@ Future putMultipartFile( // complete the multipart upload await completeMultipartUpload(etags, urls.completeURL); + + return urls.objectKey; } Future> uploadParts( diff --git a/mobile/lib/utils/xml_parser_util.dart b/mobile/lib/utils/xml_parser_util.dart index dd825fb6d4..6942394cbe 100644 --- a/mobile/lib/utils/xml_parser_util.dart +++ b/mobile/lib/utils/xml_parser_util.dart @@ -1,9 +1,14 @@ // ignore_for_file: implementation_imports -import "package:photos/utils/multipart_upload_util.dart"; import "package:xml/src/xml/entities/named_entities.dart"; import "package:xml/xml.dart"; +// used for classes that can be converted to xml +abstract class XmlParsableObject { + Map toMap(); + String get elementName; +} + // for converting the response to xml String convertJs2Xml(Map json) { final builder = XmlBuilder(); @@ -15,6 +20,7 @@ String convertJs2Xml(Map json) { ); } +// for building the xml node tree recursively void buildXml(XmlBuilder builder, dynamic node) { if (node is Map) { node.forEach((key, value) { @@ -24,22 +30,11 @@ void buildXml(XmlBuilder builder, dynamic node) { for (var item in node) { buildXml(builder, item); } - } else if (node is PartETag) { + } else if (node is XmlParsableObject) { builder.element( - "Part", + node.elementName, nest: () { - builder.element( - "PartNumber", - nest: () { - buildXml(builder, node.partNumber); - }, - ); - builder.element( - "ETag", - nest: () { - buildXml(builder, node.eTag); - }, - ); + buildXml(builder, node.toMap()); }, ); } else { @@ -47,6 +42,8 @@ void buildXml(XmlBuilder builder, dynamic node) { } } +// for removing the " from the xml string response. +// couldn't find better way to do this XmlEntityMapping defaultMyEntityMapping = MyXmlDefaultEntityMapping.xml(); class MyXmlDefaultEntityMapping extends XmlDefaultEntityMapping { From de06c8f38b96c7f7ac7ea2e3d0476e7d8f724567 Mon Sep 17 00:00:00 2001 From: Prateek Sunal Date: Sat, 13 Apr 2024 14:02:11 +0530 Subject: [PATCH 17/70] fix: use better way to remove quotes --- mobile/lib/utils/multipart_upload_util.dart | 2 +- mobile/lib/utils/xml_parser_util.dart | 92 --------------------- 2 files changed, 1 insertion(+), 93 deletions(-) diff --git a/mobile/lib/utils/multipart_upload_util.dart b/mobile/lib/utils/multipart_upload_util.dart index fc4ac4860c..29830fcef5 100644 --- a/mobile/lib/utils/multipart_upload_util.dart +++ b/mobile/lib/utils/multipart_upload_util.dart @@ -135,7 +135,7 @@ Future completeMultipartUpload( ), ) .toList(), - }); + }).replaceAll('"', '').replaceAll('"', ''); try { await _dio.post( diff --git a/mobile/lib/utils/xml_parser_util.dart b/mobile/lib/utils/xml_parser_util.dart index 6942394cbe..b4ea64b9c1 100644 --- a/mobile/lib/utils/xml_parser_util.dart +++ b/mobile/lib/utils/xml_parser_util.dart @@ -41,95 +41,3 @@ void buildXml(XmlBuilder builder, dynamic node) { builder.text(node.toString()); } } - -// for removing the " from the xml string response. -// couldn't find better way to do this -XmlEntityMapping defaultMyEntityMapping = MyXmlDefaultEntityMapping.xml(); - -class MyXmlDefaultEntityMapping extends XmlDefaultEntityMapping { - MyXmlDefaultEntityMapping.xml() : this(xmlEntities); - MyXmlDefaultEntityMapping.html() : this(htmlEntities); - MyXmlDefaultEntityMapping.html5() : this(html5Entities); - MyXmlDefaultEntityMapping(super.entities); - - @override - String encodeText(String input) => - input.replaceAllMapped(_textPattern, _textReplace); - - @override - String encodeAttributeValue(String input, XmlAttributeType type) { - switch (type) { - case XmlAttributeType.SINGLE_QUOTE: - return input.replaceAllMapped( - _singeQuoteAttributePattern, - _singeQuoteAttributeReplace, - ); - case XmlAttributeType.DOUBLE_QUOTE: - return input.replaceAllMapped( - _doubleQuoteAttributePattern, - _doubleQuoteAttributeReplace, - ); - } - } -} - -final _textPattern = RegExp(r'[&<>' + _highlyDiscouragedCharClass + r']'); - -String _textReplace(Match match) { - final toEscape = match.group(0)!; - switch (toEscape) { - case '<': - return '<'; - case '&': - return '&'; - case '>': - return '>'; - default: - return _asNumericCharacterReferences(toEscape); - } -} - -final _singeQuoteAttributePattern = - RegExp(r"['&<>\n\r\t" + _highlyDiscouragedCharClass + r']'); - -String _singeQuoteAttributeReplace(Match match) { - final toEscape = match.group(0)!; - switch (toEscape) { - case "'": - return ''; - case '&': - return '&'; - case '<': - return '<'; - case '>': - return '>'; - default: - return _asNumericCharacterReferences(toEscape); - } -} - -final _doubleQuoteAttributePattern = - RegExp(r'["&<>\n\r\t' + _highlyDiscouragedCharClass + r']'); - -String _doubleQuoteAttributeReplace(Match match) { - final toEscape = match.group(0)!; - switch (toEscape) { - case '"': - return ''; - case '&': - return '&'; - case '<': - return '<'; - case '>': - return '>'; - default: - return _asNumericCharacterReferences(toEscape); - } -} - -const _highlyDiscouragedCharClass = - r'\u0001-\u0008\u000b\u000c\u000e-\u001f\u007f-\u0084\u0086-\u009f'; - -String _asNumericCharacterReferences(String toEscape) => toEscape.runes - .map((rune) => '&#x${rune.toRadixString(16).toUpperCase()};') - .join(); From 564ca440e713d6e9604da4897ad3c8703bdbd194 Mon Sep 17 00:00:00 2001 From: Prateek Sunal Date: Sat, 13 Apr 2024 14:03:54 +0530 Subject: [PATCH 18/70] fix: remove unwanted line --- mobile/lib/utils/xml_parser_util.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/mobile/lib/utils/xml_parser_util.dart b/mobile/lib/utils/xml_parser_util.dart index b4ea64b9c1..19c9422c82 100644 --- a/mobile/lib/utils/xml_parser_util.dart +++ b/mobile/lib/utils/xml_parser_util.dart @@ -16,7 +16,6 @@ String convertJs2Xml(Map json) { return builder.buildDocument().toXmlString( pretty: true, indent: ' ', - entityMapping: defaultMyEntityMapping, ); } From 0a06ee1f55e76881a8f7cc1f1058552ae254459a Mon Sep 17 00:00:00 2001 From: Prateek Sunal Date: Sat, 13 Apr 2024 14:04:06 +0530 Subject: [PATCH 19/70] chore: lint fix --- mobile/lib/utils/xml_parser_util.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/mobile/lib/utils/xml_parser_util.dart b/mobile/lib/utils/xml_parser_util.dart index 19c9422c82..9490fc40cb 100644 --- a/mobile/lib/utils/xml_parser_util.dart +++ b/mobile/lib/utils/xml_parser_util.dart @@ -1,6 +1,5 @@ // ignore_for_file: implementation_imports -import "package:xml/src/xml/entities/named_entities.dart"; import "package:xml/xml.dart"; // used for classes that can be converted to xml From 51d02177ad28ce74f779f159125a60fedcbd2447 Mon Sep 17 00:00:00 2001 From: Prateek Sunal Date: Sat, 13 Apr 2024 14:07:20 +0530 Subject: [PATCH 20/70] chore: bump dependencies --- mobile/lib/db/device_files_db.dart | 8 +- mobile/lib/generated/intl/messages_zh.dart | 2 +- mobile/lib/services/notification_service.dart | 7 +- mobile/pubspec.lock | 168 +++++++++--------- mobile/pubspec.yaml | 6 +- 5 files changed, 91 insertions(+), 100 deletions(-) diff --git a/mobile/lib/db/device_files_db.dart b/mobile/lib/db/device_files_db.dart index ec1074eae8..94e5ac8e57 100644 --- a/mobile/lib/db/device_files_db.dart +++ b/mobile/lib/db/device_files_db.dart @@ -190,11 +190,11 @@ extension DeviceFiles on FilesDB { [ pathEntity.name, localID, - pathEntity.assetCount, + await pathEntity.assetCountAsync, pathEntity.id, pathEntity.name, localID, - pathEntity.assetCount, + await pathEntity.assetCountAsync, ], ); if (rowUpdated > 0) { @@ -208,7 +208,7 @@ extension DeviceFiles on FilesDB { { "id": pathEntity.id, "name": pathEntity.name, - "count": pathEntity.assetCount, + "count": await pathEntity.assetCountAsync, "cover_id": localID, "should_backup": shouldBackup ? _sqlBoolTrue : _sqlBoolFalse, }, @@ -339,7 +339,7 @@ extension DeviceFiles on FilesDB { int ownerID, ) async { final db = await database; - const String rawQuery = ''' + const String rawQuery = ''' SELECT ${FilesDB.columnLocalID}, ${FilesDB.columnUploadedFileID}, ${FilesDB.columnFileSize} FROM ${FilesDB.filesTable} 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, diff --git a/mobile/lib/services/notification_service.dart b/mobile/lib/services/notification_service.dart index ca9be19b54..c860f427f8 100644 --- a/mobile/lib/services/notification_service.dart +++ b/mobile/lib/services/notification_service.dart @@ -23,9 +23,8 @@ class NotificationService { Future 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 a53c6b680a..c7aa74259c 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -269,10 +269,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: @@ -311,10 +311,10 @@ packages: dependency: transitive description: name: coverage - sha256: "2fb815080e44a09b85e0f2ca8a820b15053982b2e714b59267719e8a9ff17097" + sha256: "8acabb8306b57a409bf4c83522065672ee13179297a6bb0cb9ead73948df7c76" url: "https://pub.dev" source: hosted - version: "1.6.3" + version: "1.7.2" cross_file: dependency: "direct main" description: @@ -535,10 +535,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: @@ -706,26 +706,26 @@ packages: dependency: "direct main" description: name: flutter_local_notifications - sha256: f222919a34545931e47b06000836b5101baeffb0e6eb5a4691d2d42851740dd9 + sha256: a701df4866f9a38bb8e4450a54c143bbeeb0ce2381e7df5a36e1006f3b43bb28 url: "https://pub.dev" source: hosted - version: "12.0.4" + version: "17.0.1" 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 @@ -1127,6 +1127,30 @@ packages: url: "https://pub.dev" source: hosted version: "0.9.0" + 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: @@ -1219,18 +1243,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: @@ -1315,10 +1339,10 @@ packages: dependency: transitive description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.11.0" mgrs_dart: dependency: transitive description: @@ -1462,10 +1486,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: @@ -1590,10 +1614,18 @@ packages: 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 +1646,10 @@ packages: dependency: transitive description: name: platform - sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.4" plugin_platform_interface: dependency: transitive description: @@ -1654,10 +1686,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: @@ -1798,26 +1830,10 @@ packages: dependency: "direct main" description: name: share_plus - sha256: f582d5741930f3ad1bf0211d358eddc0508cc346e5b4b248bd1e569c995ebb7a + sha256: "3ef39599b00059db0990ca2e30fca0a29d8b37aae924d60063f8e0184cf20900" 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: "7.2.2" share_plus_platform_interface: dependency: transitive description: @@ -1826,22 +1842,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.3.1" - 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: @@ -2035,10 +2035,10 @@ packages: 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 +2051,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 +2123,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: @@ -2380,10 +2380,10 @@ packages: dependency: transitive description: name: vm_service - sha256: c620a6f783fa22436da68e42db7ebbf18b8c44b9a46ab911f666ff09ffd9153f + sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 url: "https://pub.dev" source: hosted - version: "11.7.1" + version: "13.0.0" volume_controller: dependency: transitive description: @@ -2424,14 +2424,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" - web: - dependency: transitive - description: - name: web - sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 - url: "https://pub.dev" - source: hosted - version: "0.1.4-beta" web_socket_channel: dependency: transitive description: @@ -2444,10 +2436,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: @@ -2460,10 +2452,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: @@ -2500,10 +2492,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: "direct main" description: @@ -2537,5 +2529,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.1.0 <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 a3b821a814..0a87700ddb 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 @@ -131,7 +131,7 @@ dependencies: path_provider: ^2.1.1 pedantic: ^1.9.2 permission_handler: ^11.0.1 - photo_manager: ^2.8.1 + photo_manager: ^3.0.0 photo_view: ^0.14.0 pinput: ^1.2.2 pointycastle: ^3.7.3 @@ -141,7 +141,7 @@ dependencies: scrollable_positioned_list: ^0.3.5 sentry: ^7.9.0 sentry_flutter: ^7.9.0 - share_plus: ^4.0.10 + share_plus: ^7.2.2 shared_preferences: ^2.0.5 sqflite: ^2.3.0 sqflite_migration: ^0.3.0 From 17507cce6894b457485b2e0f6503213cdc743b5d Mon Sep 17 00:00:00 2001 From: Prateek Sunal Date: Sat, 13 Apr 2024 14:09:52 +0530 Subject: [PATCH 21/70] fix: remove unused constants --- mobile/lib/core/constants.dart | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/mobile/lib/core/constants.dart b/mobile/lib/core/constants.dart index 640af728b3..1cd9da1dd1 100644 --- a/mobile/lib/core/constants.dart +++ b/mobile/lib/core/constants.dart @@ -1,5 +1,3 @@ -import "package:photos/utils/crypto_util.dart"; - const int thumbnailSmallSize = 256; const int thumbnailQuality = 50; const int thumbnailLargeSize = 512; @@ -50,11 +48,6 @@ class FFDefault { // this is the chunk size of the un-encrypted file which is read and encrypted before uploading it as a single part. const multipartPartSize = 20 * 1024 * 1024; -const fileReaderChunkSize = encryptionChunkSize; - -final fileChunksCombinedForAUploadPart = - (multipartPartSize / fileReaderChunkSize).floor(); - const kDefaultProductionEndpoint = 'https://api.ente.io'; const int intMaxValue = 9223372036854775807; @@ -81,11 +74,11 @@ const kSearchSectionLimit = 9; const iOSGroupID = "group.io.ente.frame.SlideshowWidget"; -const blackThumbnailBase64 = '/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQEBAQEB' + - 'AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQ' + - 'EBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARC' + - 'ACWASwDAREAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUF' + - 'BAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk' + +const blackThumbnailBase64 = '/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQEBAQEB' + 'AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQ' + 'EBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARC' + 'ACWASwDAREAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUF' + 'BAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk' + '6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztL' + 'W2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAA' + 'AAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVY' + From 372ced25024c48f3db08d532a52cbac892b4bee0 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Sat, 13 Apr 2024 16:48:36 +0530 Subject: [PATCH 22/70] [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 23/70] [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 24/70] [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 25/70] [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 26/70] 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 27/70] 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 28/70] [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 29/70] [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 30/70] [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 31/70] [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 32/70] [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 33/70] [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 34/70] [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 35/70] [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 36/70] 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 37/70] 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 38/70] 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 8d24a489f6de287f416548e43d9777517afddddd Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 15 Apr 2024 10:45:45 +0530 Subject: [PATCH 39/70] [desktop] Fix payment redirect Fixes: https://github.com/ente-io/ente/issues/1440 There were two issues: - It was a backward incompatible change to change the scheme from ente:// to next://. Revert. - We also need to setup a top level redirect when the user presses back without making any changes to their subscription. **Tested by** Running payments app and desktop app locally, and verifying that after interactions with the payments endpoint we go back to the desktop app's actual contents correctly. --- desktop/src/main.ts | 4 ++-- web/apps/payments/README.md | 5 +++-- web/apps/payments/src/services/billing-service.ts | 8 ++++++++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/desktop/src/main.ts b/desktop/src/main.ts index 5425a0b5e5..4837210c87 100644 --- a/desktop/src/main.ts +++ b/desktop/src/main.ts @@ -32,7 +32,7 @@ import { isDev } from "./main/util"; /** * The URL where the renderer HTML is being served from. */ -export const rendererURL = "next://app"; +export const rendererURL = "ente://app"; /** * We want to hide our window instead of closing it when the user presses the @@ -63,7 +63,7 @@ export const allowWindowClose = (): void => { * production mode and `next dev` in development mode, whilst keeping the rest * of our code the same. * - * It uses protocol handlers to serve files from the "next://app" protocol + * It uses protocol handlers to serve files from the "ente://" protocol. * * - In development this is proxied to http://localhost:3000 * - In production it serves files from the `/out` directory diff --git a/web/apps/payments/README.md b/web/apps/payments/README.md index 959bedabe8..ebf3a63901 100644 --- a/web/apps/payments/README.md +++ b/web/apps/payments/README.md @@ -73,8 +73,9 @@ stripe: key: stripe_dev_key webhook-secret: stripe_dev_webhook_secret whitelisted-redirect-urls: - - "http://localhost:3000/gallery" - - "http://192.168.1.2:3001/frameRedirect" + - http://localhost:3000/gallery + - http://localhost:3001/desktop-redirect + - http://192.168.1.2:3001/frameRedirect path: success: ?status=success&session_id={CHECKOUT_SESSION_ID} cancel: ?status=fail&reason=canceled diff --git a/web/apps/payments/src/services/billing-service.ts b/web/apps/payments/src/services/billing-service.ts index 35f67660c0..9eb4fe1d5f 100644 --- a/web/apps/payments/src/services/billing-service.ts +++ b/web/apps/payments/src/services/billing-service.ts @@ -9,6 +9,12 @@ import { loadStripe } from "@stripe/stripe-js"; * redirect to the client or to some fallback URL. */ export const parseAndHandleRequest = async () => { + // See: [Note: Intercept payments redirection to desktop app] + if (window.location.pathname == "/desktop-redirect") { + window.location.href = "ente://app"; + return; + } + try { const urlParams = new URLSearchParams(window.location.search); const productID = urlParams.get("productID"); @@ -291,6 +297,8 @@ const redirectToApp = ( status: RedirectStatus, reason?: FailureReason, ) => { + // [Note: Intercept payments redirection to desktop app] + // // The desktop app passes "/desktop-redirect" as `redirectURL`. // This is just a placeholder, we want to intercept this and instead // redirect to the ente:// scheme protocol handler that is internally being From 2638a06551f98de2c5a6a7934d394f0847ce1a37 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 15 Apr 2024 10:56:41 +0530 Subject: [PATCH 40/70] [mob][photos] Enable multiPart upload for internal users --- mobile/lib/utils/file_uploader.dart | 13 +++++++++---- mobile/lib/utils/multipart_upload_util.dart | 5 +++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/mobile/lib/utils/file_uploader.dart b/mobile/lib/utils/file_uploader.dart index c60ef3e861..a545605e99 100644 --- a/mobile/lib/utils/file_uploader.dart +++ b/mobile/lib/utils/file_uploader.dart @@ -29,6 +29,7 @@ import "package:photos/models/metadata/file_magic.dart"; import 'package:photos/models/upload_url.dart'; import "package:photos/models/user_details.dart"; import 'package:photos/services/collections_service.dart'; +import "package:photos/services/feature_flag_service.dart"; import "package:photos/services/file_magic_service.dart"; import 'package:photos/services/local_sync_service.dart'; import 'package:photos/services/sync_service.dart'; @@ -493,11 +494,15 @@ class FileUploader { final String thumbnailObjectKey = await _putFile(thumbnailUploadURL, encryptedThumbnailFile); - final count = await calculatePartCount( - await encryptedFile.length(), - ); + // Calculate the number of parts for the file. Multiple part upload + // is only enabled for internal users and debug builds till it's battle tested. + final count = FeatureFlagService.instance.isInternalUserOrDebugBuild() + ? await calculatePartCount( + await encryptedFile.length(), + ) + : 1; - String fileObjectKey; + late String fileObjectKey; if (count <= 1) { final fileUploadURL = await _getUploadURL(); diff --git a/mobile/lib/utils/multipart_upload_util.dart b/mobile/lib/utils/multipart_upload_util.dart index 29830fcef5..6e0eda8ca6 100644 --- a/mobile/lib/utils/multipart_upload_util.dart +++ b/mobile/lib/utils/multipart_upload_util.dart @@ -6,6 +6,7 @@ import "package:dio/dio.dart"; import "package:logging/logging.dart"; import "package:photos/core/constants.dart"; import "package:photos/core/network/network.dart"; +import "package:photos/services/feature_flag_service.dart"; import "package:photos/utils/xml_parser_util.dart"; final _enteDio = NetworkClient.instance.enteDio; @@ -56,6 +57,10 @@ Future calculatePartCount(int fileSize) async { Future getMultipartUploadURLs(int count) async { try { + assert( + FeatureFlagService.instance.isInternalUserOrDebugBuild(), + "Multipart upload should not be enabled for external users.", + ); final response = await _enteDio.get( "/files/multipart-upload-urls", queryParameters: { From 95c0f53d212313349b3294d5ce2ccfb0bbe465b3 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 15 Apr 2024 10:56:06 +0530 Subject: [PATCH 41/70] Preserve parameters This was needed for the purchase success to be relayed back. --- web/apps/payments/src/services/billing-service.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/web/apps/payments/src/services/billing-service.ts b/web/apps/payments/src/services/billing-service.ts index 9eb4fe1d5f..c0ba5da1e7 100644 --- a/web/apps/payments/src/services/billing-service.ts +++ b/web/apps/payments/src/services/billing-service.ts @@ -11,7 +11,9 @@ import { loadStripe } from "@stripe/stripe-js"; export const parseAndHandleRequest = async () => { // See: [Note: Intercept payments redirection to desktop app] if (window.location.pathname == "/desktop-redirect") { - window.location.href = "ente://app"; + const desktopRedirectURL = new URL("ente://app/gallery"); + desktopRedirectURL.search = new URL(window.location.href).search; + window.location.href = desktopRedirectURL.href; return; } From 896cf0f785aa2973258912e2e609de8e74cb41ce Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 15 Apr 2024 11:50:23 +0530 Subject: [PATCH 42/70] 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 43/70] 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 44/70] 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 45/70] 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 46/70] 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 47/70] 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 48/70] 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 49/70] [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 50/70] [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 51/70] 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 52/70] [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 53/70] 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 54/70] 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 55/70] [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 56/70] 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 57/70] 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 58/70] 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 59/70] 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 60/70] 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 61/70] 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 62/70] 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 63/70] 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 64/70] 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 587f72168308ae59e2a7244ee1db815719f9c88f Mon Sep 17 00:00:00 2001 From: Prateek Sunal Date: Mon, 15 Apr 2024 21:43:30 +0530 Subject: [PATCH 65/70] 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 311d23873efc1aeeab0a9042337b8422d2b0ddac Mon Sep 17 00:00:00 2001 From: Prateek Sunal Date: Mon, 15 Apr 2024 21:44:49 +0530 Subject: [PATCH 66/70] 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 67/70] 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 d7b0beb949a8e2e659f7669f5598a5189e92113d Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 16 Apr 2024 09:03:35 +0530 Subject: [PATCH 68/70] [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 69/70] [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 3b5a2e9d2a1f3e193755f03a0c1316fff0bc4e99 Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Tue, 16 Apr 2024 11:36:35 +0530 Subject: [PATCH 70/70] [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