mirror of
				https://github.com/KevinMidboe/immich.git
				synced 2025-10-29 17:40:28 +00:00 
			
		
		
		
	fix(mobile): images rendered twice due to rebuild (#4060)
* fix(mobile): images rendered twice due to rebuild * fix bottom sheet triggered multiple times
This commit is contained in:
		
				
					committed by
					
						
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							d023d5b6b4
						
					
				
				
					commit
					bd226e9e2c
				
			@@ -7,6 +7,8 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
			
		||||
import 'package:immich_mobile/modules/asset_viewer/ui/description_input.dart';
 | 
			
		||||
import 'package:immich_mobile/modules/map/ui/map_thumbnail.dart';
 | 
			
		||||
import 'package:immich_mobile/shared/models/asset.dart';
 | 
			
		||||
import 'package:immich_mobile/shared/models/exif_info.dart';
 | 
			
		||||
import 'package:immich_mobile/shared/providers/asset.provider.dart';
 | 
			
		||||
import 'package:immich_mobile/shared/ui/drag_sheet.dart';
 | 
			
		||||
import 'package:latlong2/latlong.dart';
 | 
			
		||||
import 'package:immich_mobile/utils/bytes_units.dart';
 | 
			
		||||
@@ -17,11 +19,12 @@ class ExifBottomSheet extends HookConsumerWidget {
 | 
			
		||||
 | 
			
		||||
  const ExifBottomSheet({Key? key, required this.asset}) : super(key: key);
 | 
			
		||||
 | 
			
		||||
  bool get hasCoordinates =>
 | 
			
		||||
      asset.exifInfo?.latitude != null &&
 | 
			
		||||
      asset.exifInfo?.longitude != null &&
 | 
			
		||||
      asset.exifInfo!.latitude! != 0 &&
 | 
			
		||||
      asset.exifInfo!.longitude! != 0;
 | 
			
		||||
  bool hasCoordinates(ExifInfo? exifInfo) =>
 | 
			
		||||
      exifInfo != null &&
 | 
			
		||||
      exifInfo.latitude != null &&
 | 
			
		||||
      exifInfo.longitude != null &&
 | 
			
		||||
      exifInfo.latitude != 0 &&
 | 
			
		||||
      exifInfo.longitude != 0;
 | 
			
		||||
 | 
			
		||||
  String get formattedDateTime {
 | 
			
		||||
    final fileCreatedAt = asset.fileCreatedAt.toLocal();
 | 
			
		||||
@@ -31,13 +34,13 @@ class ExifBottomSheet extends HookConsumerWidget {
 | 
			
		||||
    return '$date • $time';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Future<Uri?> _createCoordinatesUri() async {
 | 
			
		||||
    if (!hasCoordinates) {
 | 
			
		||||
  Future<Uri?> _createCoordinatesUri(ExifInfo? exifInfo) async {
 | 
			
		||||
    if (!hasCoordinates(exifInfo)) {
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    double latitude = asset.exifInfo!.latitude!;
 | 
			
		||||
    double longitude = asset.exifInfo!.longitude!;
 | 
			
		||||
    final double latitude = exifInfo!.latitude!;
 | 
			
		||||
    final double longitude = exifInfo.longitude!;
 | 
			
		||||
 | 
			
		||||
    const zoomLevel = 16;
 | 
			
		||||
 | 
			
		||||
@@ -75,7 +78,8 @@ class ExifBottomSheet extends HookConsumerWidget {
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context, WidgetRef ref) {
 | 
			
		||||
    final exifInfo = asset.exifInfo;
 | 
			
		||||
    final assetWithExif = ref.watch(assetDetailProvider(asset));
 | 
			
		||||
    final exifInfo = (assetWithExif.value ?? asset).exifInfo;
 | 
			
		||||
    var isDarkTheme = Theme.of(context).brightness == Brightness.dark;
 | 
			
		||||
    var textColor = isDarkTheme ? Colors.white : Colors.black;
 | 
			
		||||
 | 
			
		||||
@@ -104,7 +108,7 @@ class ExifBottomSheet extends HookConsumerWidget {
 | 
			
		||||
                ),
 | 
			
		||||
              ],
 | 
			
		||||
              onTap: (tapPosition, latLong) async {
 | 
			
		||||
                Uri? uri = await _createCoordinatesUri();
 | 
			
		||||
                Uri? uri = await _createCoordinatesUri(exifInfo);
 | 
			
		||||
 | 
			
		||||
                if (uri == null) {
 | 
			
		||||
                  return;
 | 
			
		||||
@@ -146,7 +150,7 @@ class ExifBottomSheet extends HookConsumerWidget {
 | 
			
		||||
 | 
			
		||||
    buildLocation() {
 | 
			
		||||
      // Guard no lat/lng
 | 
			
		||||
      if (!hasCoordinates) {
 | 
			
		||||
      if (!hasCoordinates(exifInfo)) {
 | 
			
		||||
        return Container();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
@@ -211,7 +215,6 @@ class ExifBottomSheet extends HookConsumerWidget {
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    buildImageProperties() {
 | 
			
		||||
      // Helper to create the ListTile and avoid repeating code
 | 
			
		||||
      createImagePropertiesListStyle(title, subtitle) => ListTile(
 | 
			
		||||
@@ -334,7 +337,7 @@ class ExifBottomSheet extends HookConsumerWidget {
 | 
			
		||||
                          crossAxisAlignment: CrossAxisAlignment.start,
 | 
			
		||||
                          children: [
 | 
			
		||||
                            Flexible(
 | 
			
		||||
                              flex: hasCoordinates ? 5 : 0,
 | 
			
		||||
                              flex: hasCoordinates(exifInfo) ? 5 : 0,
 | 
			
		||||
                              child: Padding(
 | 
			
		||||
                                padding: const EdgeInsets.only(right: 8.0),
 | 
			
		||||
                                child: buildLocation(),
 | 
			
		||||
@@ -364,7 +367,7 @@ class ExifBottomSheet extends HookConsumerWidget {
 | 
			
		||||
                    if (asset.isRemote) DescriptionInput(asset: asset),
 | 
			
		||||
                    const SizedBox(height: 8.0),
 | 
			
		||||
                    buildLocation(),
 | 
			
		||||
                    SizedBox(height: hasCoordinates ? 16.0 : 0.0),
 | 
			
		||||
                    SizedBox(height: hasCoordinates(exifInfo) ? 16.0 : 0.0),
 | 
			
		||||
                    buildDetail(),
 | 
			
		||||
                    const SizedBox(height: 50),
 | 
			
		||||
                  ],
 | 
			
		||||
 
 | 
			
		||||
@@ -64,9 +64,8 @@ class GalleryViewerPage extends HookConsumerWidget {
 | 
			
		||||
    final authToken = 'Bearer ${Store.get(StoreKey.accessToken)}';
 | 
			
		||||
    final currentIndex = useState(initialIndex);
 | 
			
		||||
    final currentAsset = loadAsset(currentIndex.value);
 | 
			
		||||
    final watchedAsset = ref.watch(assetDetailProvider(currentAsset));
 | 
			
		||||
 | 
			
		||||
    Asset asset() => watchedAsset.value ?? currentAsset;
 | 
			
		||||
    Asset asset() => currentAsset;
 | 
			
		||||
 | 
			
		||||
    useEffect(
 | 
			
		||||
      () {
 | 
			
		||||
@@ -194,7 +193,7 @@ class GalleryViewerPage extends HookConsumerWidget {
 | 
			
		||||
            padding: EdgeInsets.only(
 | 
			
		||||
              bottom: MediaQuery.of(context).viewInsets.bottom,
 | 
			
		||||
            ),
 | 
			
		||||
            child: ExifBottomSheet(asset: asset()),
 | 
			
		||||
            child: ExifBottomSheet(asset: currentAsset),
 | 
			
		||||
          );
 | 
			
		||||
        },
 | 
			
		||||
      );
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,12 @@
 | 
			
		||||
import 'package:auto_route/auto_route.dart';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:flutter/services.dart';
 | 
			
		||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
			
		||||
import 'package:immich_mobile/routing/router.dart';
 | 
			
		||||
import 'package:immich_mobile/shared/models/asset.dart';
 | 
			
		||||
import 'package:immich_mobile/shared/ui/immich_image.dart';
 | 
			
		||||
import 'package:immich_mobile/utils/storage_indicator.dart';
 | 
			
		||||
 | 
			
		||||
class ThumbnailImage extends HookConsumerWidget {
 | 
			
		||||
class ThumbnailImage extends StatelessWidget {
 | 
			
		||||
  final Asset asset;
 | 
			
		||||
  final int index;
 | 
			
		||||
  final Asset Function(int index) loadAsset;
 | 
			
		||||
@@ -36,7 +35,7 @@ class ThumbnailImage extends HookConsumerWidget {
 | 
			
		||||
  }) : super(key: key);
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context, WidgetRef ref) {
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    final isDarkTheme = Theme.of(context).brightness == Brightness.dark;
 | 
			
		||||
    final assetContainerColor =
 | 
			
		||||
        isDarkTheme ? Colors.blueGrey : Theme.of(context).primaryColorLight;
 | 
			
		||||
@@ -61,8 +60,8 @@ class ThumbnailImage extends HookConsumerWidget {
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Widget buildImage(Asset asset) {
 | 
			
		||||
      var image = SizedBox(
 | 
			
		||||
    Widget buildImage() {
 | 
			
		||||
      final image = SizedBox(
 | 
			
		||||
        width: 300,
 | 
			
		||||
        height: 300,
 | 
			
		||||
        child: Hero(
 | 
			
		||||
@@ -133,7 +132,7 @@ class ThumbnailImage extends HookConsumerWidget {
 | 
			
		||||
                    )
 | 
			
		||||
                  : const Border(),
 | 
			
		||||
            ),
 | 
			
		||||
            child: buildImage(asset),
 | 
			
		||||
            child: buildImage(),
 | 
			
		||||
          ),
 | 
			
		||||
          if (multiselectEnabled)
 | 
			
		||||
            Padding(
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user