Procházet zdrojové kódy

Minor performance improvements during swipe b/w photos (#1361)

Neeraj Gupta před 1 rokem
rodič
revize
d67efccf8c

+ 11 - 2
lib/generated/intl/messages_it.dart

@@ -230,7 +230,7 @@ class MessageLookup extends MessageLookupByLibrary {
             MessageLookupByLibrary.simpleMessage("Aggiungi all\'album"),
         "addToEnte": MessageLookupByLibrary.simpleMessage("Aggiungi su ente"),
         "addToHiddenAlbum":
-            MessageLookupByLibrary.simpleMessage("Add to hidden album"),
+            MessageLookupByLibrary.simpleMessage("Aggiungi ad album nascosto"),
         "addViewer":
             MessageLookupByLibrary.simpleMessage("Aggiungi in sola lettura"),
         "addedAs": MessageLookupByLibrary.simpleMessage("Aggiunto come"),
@@ -707,6 +707,8 @@ class MessageLookup extends MessageLookupByLibrary {
         "goToSettings":
             MessageLookupByLibrary.simpleMessage("Vai alle impostazioni"),
         "googlePlayId": MessageLookupByLibrary.simpleMessage("Google Play ID"),
+        "grantFullAccessPrompt": MessageLookupByLibrary.simpleMessage(
+            "Consenti l\'accesso a tutte le foto nelle Impostazioni"),
         "grantPermission":
             MessageLookupByLibrary.simpleMessage("Concedi il permesso"),
         "groupNearbyPhotos": MessageLookupByLibrary.simpleMessage(
@@ -861,7 +863,7 @@ class MessageLookup extends MessageLookupByLibrary {
         "moveToAlbum":
             MessageLookupByLibrary.simpleMessage("Sposta nell\'album"),
         "moveToHiddenAlbum":
-            MessageLookupByLibrary.simpleMessage("Move to hidden album"),
+            MessageLookupByLibrary.simpleMessage("Sposta in album nascosto"),
         "movedSuccessfullyTo": m30,
         "movedToTrash":
             MessageLookupByLibrary.simpleMessage("Spostato nel cestino"),
@@ -910,6 +912,8 @@ class MessageLookup extends MessageLookupByLibrary {
             "Ops, impossibile salvare le modifiche"),
         "oopsSomethingWentWrong": MessageLookupByLibrary.simpleMessage(
             "Oops! Qualcosa è andato storto"),
+        "openSettings":
+            MessageLookupByLibrary.simpleMessage("Apri Impostazioni"),
         "openTheItem":
             MessageLookupByLibrary.simpleMessage("• Apri la foto o il video"),
         "openstreetmapContributors": MessageLookupByLibrary.simpleMessage(
@@ -980,6 +984,8 @@ class MessageLookup extends MessageLookupByLibrary {
         "preserveMore": MessageLookupByLibrary.simpleMessage("Salva più foto"),
         "pressAndHoldToPlayVideo": MessageLookupByLibrary.simpleMessage(
             "Tieni premuto per riprodurre il video"),
+        "pressAndHoldToPlayVideoDetailed": MessageLookupByLibrary.simpleMessage(
+            "Tieni premuto sull\'immagine per riprodurre il video"),
         "privacy": MessageLookupByLibrary.simpleMessage("Privacy"),
         "privacyPolicyTitle":
             MessageLookupByLibrary.simpleMessage("Privacy Policy"),
@@ -1116,6 +1122,8 @@ class MessageLookup extends MessageLookupByLibrary {
             "Seleziona gli elementi da aggiungere"),
         "selectLanguage":
             MessageLookupByLibrary.simpleMessage("Seleziona una lingua"),
+        "selectMorePhotos":
+            MessageLookupByLibrary.simpleMessage("Seleziona più foto"),
         "selectReason":
             MessageLookupByLibrary.simpleMessage("Seleziona un motivo"),
         "selectYourPlan":
@@ -1180,6 +1188,7 @@ class MessageLookup extends MessageLookupByLibrary {
             MessageLookupByLibrary.simpleMessage("Condivise con te"),
         "sharing":
             MessageLookupByLibrary.simpleMessage("Condivisione in corso..."),
+        "showMemories": MessageLookupByLibrary.simpleMessage("Mostra ricordi"),
         "signUpTerms": MessageLookupByLibrary.simpleMessage(
             "Accetto i <u-terms>termini di servizio</u-terms> e la <u-policy>politica sulla privacy</u-policy>"),
         "singleFileDeleteFromDevice": m47,

+ 3 - 0
lib/models/file/file.dart

@@ -271,6 +271,9 @@ class EnteFile {
   int get width {
     return pubMagicMetadata?.w ?? 0;
   }
+  bool get hasDimensions {
+    return height != 0 && width != 0;
+  }
 
   // returns true if the file isn't available in the user's gallery
   bool get isRemoteFile {

+ 24 - 0
lib/ui/common/fast_scroll_physics.dart

@@ -0,0 +1,24 @@
+import 'package:flutter/material.dart';
+
+class FastScrollPhysics extends PageScrollPhysics {
+  final double speedFactor;
+
+  const FastScrollPhysics({this.speedFactor = 2.0, ScrollPhysics? parent})
+      : super(parent: parent);
+
+  @override
+  FastScrollPhysics applyTo(ScrollPhysics? ancestor) {
+    return FastScrollPhysics(
+      speedFactor: speedFactor,
+      parent: buildParent(ancestor),
+    );
+  }
+
+  @override
+  Simulation? createBallisticSimulation(
+    ScrollMetrics position,
+    double velocity,
+  ) {
+    return super.createBallisticSimulation(position, velocity * speedFactor);
+  }
+}

+ 2 - 1
lib/ui/viewer/file/detail_page.dart

@@ -7,6 +7,7 @@ import 'package:photos/core/constants.dart';
 import 'package:photos/core/errors.dart';
 import "package:photos/generated/l10n.dart";
 import 'package:photos/models/file/file.dart';
+import "package:photos/ui/common/fast_scroll_physics.dart";
 import 'package:photos/ui/tools/editor/image_editor_page.dart';
 import "package:photos/ui/viewer/file/file_app_bar.dart";
 import "package:photos/ui/viewer/file/file_bottom_bar.dart";
@@ -200,7 +201,7 @@ class _DetailPageState extends State<DetailPage> {
       },
       physics: _shouldDisableScroll
           ? const NeverScrollableScrollPhysics()
-          : const PageScrollPhysics(),
+          : const FastScrollPhysics(speedFactor: 4.0),
       controller: _pageController,
       itemCount: _files!.length,
     );

+ 4 - 4
lib/ui/viewer/file/file_details_widget.dart

@@ -279,10 +279,10 @@ class _FileDetailsWidgetState extends State<FileDetailsWidget> {
             "ImageLength"];
     if (imageWidth != null && imageLength != null) {
       _exifData["resolution"] = '$imageWidth x $imageLength';
-      _exifData['megaPixels'] =
-          ((imageWidth.values.firstAsInt() * imageLength.values.firstAsInt()) /
-                  1000000)
-              .toStringAsFixed(1);
+      final double megaPixels =
+          (imageWidth.values.firstAsInt() * imageLength.values.firstAsInt()) / 1000000;
+      final double roundedMegaPixels = (megaPixels * 10).round() / 10.0;
+      _exifData['megaPixels'] = roundedMegaPixels..toStringAsFixed(1);
     } else {
       debugPrint("No image width/height");
     }

+ 57 - 41
lib/ui/viewer/file/zoomable_image.dart

@@ -1,6 +1,7 @@
 import 'dart:async';
 import 'dart:io';
 
+import "package:flutter/foundation.dart";
 import 'package:flutter/material.dart';
 import 'package:flutter/widgets.dart';
 import 'package:logging/logging.dart';
@@ -12,6 +13,7 @@ import 'package:photos/core/event_bus.dart';
 import 'package:photos/db/files_db.dart';
 import 'package:photos/events/files_updated_event.dart';
 import 'package:photos/events/local_photos_updated_event.dart';
+import "package:photos/models/file/extensions/file_props.dart";
 import 'package:photos/models/file/file.dart';
 import "package:photos/models/metadata/file_magic.dart";
 import "package:photos/services/file_magic_service.dart";
@@ -19,6 +21,7 @@ import 'package:photos/ui/common/loading_widget.dart';
 import 'package:photos/utils/file_util.dart';
 import 'package:photos/utils/image_util.dart';
 import 'package:photos/utils/thumbnail_util.dart';
+import "package:photos/utils/toast_util.dart";
 
 class ZoomableImage extends StatefulWidget {
   final EnteFile photo;
@@ -127,7 +130,6 @@ class _ZoomableImageState extends State<ZoomableImage>
       if (cachedThumbnail != null) {
         _imageProvider = Image.memory(cachedThumbnail).image;
         _loadedSmallThumbnail = true;
-        _captureThumbnailDimensions(_imageProvider!);
       } else {
         getThumbnailFromServer(_photo).then((file) {
           final imageProvider = Image.memory(file).image;
@@ -137,7 +139,6 @@ class _ZoomableImageState extends State<ZoomableImage>
                 setState(() {
                   _imageProvider = imageProvider;
                   _loadedSmallThumbnail = true;
-                  _captureThumbnailDimensions(_imageProvider!);
                 });
               }
             }).catchError((e) {
@@ -235,7 +236,10 @@ class _ZoomableImageState extends State<ZoomableImage>
     if (mounted) {
       precacheImage(imageProvider, context).then((value) async {
         if (mounted) {
-          await _updatePhotoViewController(imageProvider);
+          await _updatePhotoViewController(
+            previewImageProvider: _imageProvider,
+            finalImageProvider: imageProvider,
+          );
           setState(() {
             _imageProvider = imageProvider;
             _loadedFinalImage = true;
@@ -246,50 +250,62 @@ class _ZoomableImageState extends State<ZoomableImage>
     }
   }
 
-  Future<void> _captureThumbnailDimensions(ImageProvider imageProvider) async {
-    final imageInfo = await getImageInfo(imageProvider);
-    _thumbnailWidth = imageInfo.image.width;
-  }
-
-  Future<void> _updatePhotoViewController(ImageProvider imageProvider) async {
-    if (_thumbnailWidth == null || _photoViewController.scale == null) {
-      return;
+  Future<void> _updatePhotoViewController({
+    required ImageProvider? previewImageProvider,
+    required ImageProvider finalImageProvider,
+  }) async {
+    final bool shouldFixPosition = previewImageProvider != null &&
+        _isZooming &&
+        _photoViewController.scale != null;
+    ImageInfo? finalImageInfo;
+    if(shouldFixPosition) {
+      if (kDebugMode) {
+        showToast(context,
+            'Updating photo scale zooming: $_isZooming and scale: ${_photoViewController.scale}');
+      }
+      final prevImageInfo = await getImageInfo(previewImageProvider);
+      finalImageInfo = await getImageInfo(finalImageProvider);
+      final scale = _photoViewController.scale! /
+          (finalImageInfo.image.width / prevImageInfo.image.width);
+      final currentPosition = _photoViewController.value.position;
+      final positionScaleFactor = 1 / scale;
+      final newPosition = currentPosition.scale(
+        positionScaleFactor,
+        positionScaleFactor,
+      );
+      _photoViewController = PhotoViewController(
+        initialPosition: newPosition,
+        initialScale: scale,
+      );
+    }
+    final bool canUpdateMetadata = _photo.canEditMetaInfo;
+    // forcefully get finalImageInfo is dimensions are not available in metadata
+    if (finalImageInfo == null && canUpdateMetadata && !_photo.hasDimensions) {
+      finalImageInfo = await getImageInfo(finalImageProvider);
+    }
+    if (finalImageInfo != null && canUpdateMetadata) {
+      _updateAspectRatioIfNeeded(_photo, finalImageInfo).ignore();
     }
-    final imageInfo = await getImageInfo(imageProvider);
-    final scale = _photoViewController.scale! /
-        (imageInfo.image.width / _thumbnailWidth!);
-    final currentPosition = _photoViewController.value.position;
-    final positionScaleFactor = 1 / scale;
-    final newPosition = currentPosition.scale(
-      positionScaleFactor,
-      positionScaleFactor,
-    );
-    _photoViewController = PhotoViewController(
-      initialPosition: newPosition,
-      initialScale: scale,
-    );
-    _updateAspectRatioIfNeeded(imageInfo).ignore();
   }
 
   // Fallback logic to finish back fill and update aspect
   // ratio if needed.
-  Future<void> _updateAspectRatioIfNeeded(ImageInfo imageInfo) async {
-    if (_imageProvider != null &&
-        widget.photo.isUploaded &&
-        widget.photo.ownerID == _currentUserID) {
-      final int h = imageInfo.image.height, w = imageInfo.image.width;
-      if (h != 0 &&
-          w != 0 &&
-          (h != widget.photo.height || w != widget.photo.width)) {
-        _logger.info('Updating aspect ratio for ${widget.photo} to $h:$w');
-
-        await FileMagicService.instance.updatePublicMagicMetadata([
-          widget.photo,
-        ], {
-          heightKey: h,
-          widthKey: w,
-        });
+  Future<void> _updateAspectRatioIfNeeded(
+    EnteFile enteFile,
+    ImageInfo imageInfo,
+  ) async {
+    final int h = imageInfo.image.height, w = imageInfo.image.width;
+    if (h != enteFile.height || w != enteFile.width) {
+      if (kDebugMode) {
+        showToast(context, 'Updating aspect ratio');
       }
+      _logger.info('Updating aspect ratio for $enteFile to $h:$w');
+      await FileMagicService.instance.updatePublicMagicMetadata([
+        enteFile,
+      ], {
+        heightKey: h,
+        widthKey: w,
+      });
     }
   }
 

+ 14 - 5
lib/ui/viewer/file_details/file_properties_item_widget.dart

@@ -47,15 +47,24 @@ class _FilePropertiesItemWidgetState extends State<FilePropertiesItemWidget> {
   }
 
   Future<List<Widget>> _subTitleSection() async {
-    final bool showDimension = widget.exifData["resolution"] != null &&
-        widget.exifData["megaPixels"] != null;
+    final StringBuffer dimString = StringBuffer();
+    if (widget.exifData["resolution"] != null &&
+        widget.exifData["megaPixels"] != null) {
+      dimString.write('${widget.exifData["megaPixels"]}MP ');
+      dimString.write('${widget.exifData["resolution"]}');
+    } else if (widget.file.hasDimensions) {
+      final double megaPixels =
+          (widget.file.width * widget.file.height) / 1000000;
+      final double roundedMegaPixels = (megaPixels * 10).round() / 10.0;
+      dimString.write('${roundedMegaPixels.toStringAsFixed(1)}MP ');
+      dimString.write('${widget.file.width} x ${widget.file.height}');
+    }
     final subSectionWidgets = <Widget>[];
 
-    if (showDimension) {
+    if (dimString.isNotEmpty) {
       subSectionWidgets.add(
         Text(
-          "${widget.exifData["megaPixels"]}MP  "
-          "${widget.exifData["resolution"]}  ",
+          dimString.toString(),
           style: getEnteTextTheme(context).miniMuted,
         ),
       );