From 88214a485b6e750dc3bb1582befd490198573717 Mon Sep 17 00:00:00 2001
From: martyfuhry <martyfuhry@gmail.com>
Date: Sat, 17 Feb 2024 23:03:01 -0500
Subject: [PATCH] fix(mobile): Fixes bottom exif info sheet modal drag controls
 (#7165)

* WIPip

* Fixed show modal bottom sheet to use drag handle

* Fixes advanced bottom sheet scrolling

---------

Co-authored-by: Alex <alex.tran1502@gmail.com>
---
 .../ui/advanced_bottom_sheet.dart             | 147 ++++++++---------
 .../asset_viewer/ui/exif_bottom_sheet.dart    | 154 +++++++-----------
 .../asset_viewer/views/gallery_viewer.dart    |   6 +-
 3 files changed, 135 insertions(+), 172 deletions(-)

diff --git a/mobile/lib/modules/asset_viewer/ui/advanced_bottom_sheet.dart b/mobile/lib/modules/asset_viewer/ui/advanced_bottom_sheet.dart
index fe241fa652..9425aa303b 100644
--- a/mobile/lib/modules/asset_viewer/ui/advanced_bottom_sheet.dart
+++ b/mobile/lib/modules/asset_viewer/ui/advanced_bottom_sheet.dart
@@ -12,92 +12,85 @@ class AdvancedBottomSheet extends HookConsumerWidget {
   @override
   Widget build(BuildContext context, WidgetRef ref) {
     return SingleChildScrollView(
-      child: Card(
-        shape: const RoundedRectangleBorder(
-          borderRadius: BorderRadius.only(
-            topLeft: Radius.circular(15),
-            topRight: Radius.circular(15),
-          ),
-        ),
-        margin: const EdgeInsets.all(0),
-        child: Container(
-          margin: const EdgeInsets.symmetric(horizontal: 8.0),
-          child: LayoutBuilder(
-            builder: (context, constraints) {
-              // One column
-              return Column(
-                crossAxisAlignment: CrossAxisAlignment.stretch,
-                children: [
-                  const SizedBox(height: 32.0),
-                  const Align(
-                    child: Text(
-                      "ADVANCED INFO",
-                      style: TextStyle(fontSize: 12.0),
-                    ),
+      child: Container(
+        margin: const EdgeInsets.symmetric(horizontal: 8.0),
+        child: LayoutBuilder(
+          builder: (context, constraints) {
+            // One column
+            return Column(
+              crossAxisAlignment: CrossAxisAlignment.stretch,
+              children: [
+                const Align(
+                  child: Text(
+                    "ADVANCED INFO",
+                    style: TextStyle(fontSize: 12.0),
                   ),
-                  const SizedBox(height: 32.0),
-                  Container(
-                    decoration: BoxDecoration(
-                      color: context.isDarkTheme
-                          ? Colors.grey[900]
-                          : Colors.grey[200],
-                      borderRadius: BorderRadius.circular(15.0),
+                ),
+                const SizedBox(height: 32.0),
+                Container(
+                  decoration: BoxDecoration(
+                    color: context.isDarkTheme
+                        ? Colors.grey[900]
+                        : Colors.grey[200],
+                    borderRadius: BorderRadius.circular(15.0),
+                  ),
+                  child: Padding(
+                    padding: const EdgeInsets.only(
+                      right: 16.0,
+                      left: 16,
+                      top: 8,
+                      bottom: 16,
                     ),
-                    child: Padding(
-                      padding: const EdgeInsets.only(
-                        right: 16.0,
-                        left: 16,
-                        top: 8,
-                        bottom: 16,
-                      ),
-                      child: ListView(
-                        shrinkWrap: true,
-                        children: [
-                          Align(
-                            alignment: Alignment.centerRight,
-                            child: IconButton(
-                              onPressed: () {
-                                Clipboard.setData(
-                                  ClipboardData(text: assetDetail.toString()),
-                                ).then((_) {
-                                  ScaffoldMessenger.of(context).showSnackBar(
-                                    SnackBar(
-                                      content: Text(
-                                        "Copied to clipboard",
-                                        style: context.textTheme.bodyLarge
-                                            ?.copyWith(
-                                          color: context.primaryColor,
-                                        ),
+                    child: ListView(
+                      shrinkWrap: true,
+                      physics: const NeverScrollableScrollPhysics(),
+                      children: [
+                        Align(
+                          alignment: Alignment.centerRight,
+                          child: IconButton(
+                            onPressed: () {
+                              Clipboard.setData(
+                                ClipboardData(
+                                  text: assetDetail.toString(),
+                                ),
+                              ).then((_) {
+                                ScaffoldMessenger.of(context).showSnackBar(
+                                  SnackBar(
+                                    content: Text(
+                                      "Copied to clipboard",
+                                      style:
+                                          context.textTheme.bodyLarge?.copyWith(
+                                        color: context.primaryColor,
                                       ),
                                     ),
-                                  );
-                                });
-                              },
-                              icon: Icon(
-                                Icons.copy,
-                                size: 16.0,
-                                color: context.primaryColor,
-                              ),
+                                  ),
+                                );
+                              });
+                            },
+                            icon: Icon(
+                              Icons.copy,
+                              size: 16.0,
+                              color: context.primaryColor,
                             ),
                           ),
-                          SelectableText(
-                            assetDetail.toString(),
-                            style: const TextStyle(
-                              fontSize: 12.0,
-                              fontWeight: FontWeight.bold,
-                              fontFamily: "Inconsolata",
-                            ),
-                            showCursor: true,
+                        ),
+                        SelectableText(
+                          assetDetail.toString(),
+                          style: const TextStyle(
+                            fontSize: 12.0,
+                            fontWeight: FontWeight.bold,
+                            fontFamily: "Inconsolata",
                           ),
-                        ],
-                      ),
+                          showCursor: true,
+                        ),
+                      ],
                     ),
                   ),
-                  const SizedBox(height: 32.0),
-                ],
-              );
-            },
-          ),
+                ),
+                const SizedBox(height: 32.0),
+              ],
+            );
+          },
         ),
       ),
     );
diff --git a/mobile/lib/modules/asset_viewer/ui/exif_bottom_sheet.dart b/mobile/lib/modules/asset_viewer/ui/exif_bottom_sheet.dart
index 45d73dc71c..3c6d5f2b6c 100644
--- a/mobile/lib/modules/asset_viewer/ui/exif_bottom_sheet.dart
+++ b/mobile/lib/modules/asset_viewer/ui/exif_bottom_sheet.dart
@@ -10,7 +10,6 @@ import 'package:immich_mobile/modules/asset_viewer/ui/description_input.dart';
 import 'package:immich_mobile/modules/map/widgets/map_thumbnail.dart';
 import 'package:immich_mobile/shared/models/asset.dart';
 import 'package:immich_mobile/shared/providers/asset.provider.dart';
-import 'package:immich_mobile/shared/ui/drag_sheet.dart';
 import 'package:immich_mobile/utils/selection_handlers.dart';
 import 'package:immich_mobile/utils/bytes_units.dart';
 import 'package:maplibre_gl/maplibre_gl.dart';
@@ -126,20 +125,6 @@ class ExifBottomSheet extends HookConsumerWidget {
       return text.isNotEmpty ? text : null;
     }
 
-    buildDragHeader() {
-      return const Column(
-        crossAxisAlignment: CrossAxisAlignment.start,
-        children: [
-          SizedBox(height: 12),
-          Align(
-            alignment: Alignment.center,
-            child: CustomDraggingHandle(),
-          ),
-          SizedBox(height: 12),
-        ],
-      );
-    }
-
     buildLocation() {
       // Guard no lat/lng
       if (!hasCoordinates()) {
@@ -341,86 +326,69 @@ class ExifBottomSheet extends HookConsumerWidget {
       );
     }
 
-    return GestureDetector(
-      onTap: () {
-        // FocusScope.of(context).unfocus();
-      },
-      child: SingleChildScrollView(
-        child: Card(
-          shape: const RoundedRectangleBorder(
-            borderRadius: BorderRadius.only(
-              topLeft: Radius.circular(15),
-              topRight: Radius.circular(15),
-            ),
-          ),
-          margin: const EdgeInsets.all(0),
-          child: Container(
-            margin: const EdgeInsets.symmetric(horizontal: 16.0),
-            child: LayoutBuilder(
-              builder: (context, constraints) {
-                if (constraints.maxWidth > 600) {
-                  // Two column
-                  return Padding(
-                    padding: const EdgeInsets.symmetric(horizontal: 12.0),
-                    child: Column(
-                      crossAxisAlignment: CrossAxisAlignment.stretch,
-                      children: [
-                        buildDragHeader(),
-                        buildDate(),
-                        if (asset.isRemote) DescriptionInput(asset: asset),
-                        Row(
-                          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
-                          crossAxisAlignment: CrossAxisAlignment.start,
-                          children: [
-                            Flexible(
-                              flex: hasCoordinates() ? 5 : 0,
-                              child: Padding(
-                                padding: const EdgeInsets.only(right: 8.0),
-                                child: buildLocation(),
-                              ),
-                            ),
-                            Flexible(
-                              flex: 5,
-                              child: Padding(
-                                padding: const EdgeInsets.only(left: 8.0),
-                                child: buildDetail(),
-                              ),
-                            ),
-                          ],
+    return SingleChildScrollView(
+      padding: const EdgeInsets.symmetric(horizontal: 8.0),
+      child: Container(
+        margin: const EdgeInsets.symmetric(horizontal: 16.0),
+        child: LayoutBuilder(
+          builder: (context, constraints) {
+            if (constraints.maxWidth > 600) {
+              // Two column
+              return Column(
+                mainAxisSize: MainAxisSize.min,
+                crossAxisAlignment: CrossAxisAlignment.stretch,
+                children: [
+                  buildDate(),
+                  if (asset.isRemote) DescriptionInput(asset: asset),
+                  Row(
+                    mainAxisAlignment: MainAxisAlignment.start,
+                    crossAxisAlignment: CrossAxisAlignment.start,
+                    children: [
+                      Expanded(
+                        child: Padding(
+                          padding: const EdgeInsets.only(right: 8.0),
+                          child: buildLocation(),
                         ),
-                        const SizedBox(height: 50),
-                      ],
-                    ),
-                  );
-                }
+                      ),
+                      ConstrainedBox(
+                        constraints: const BoxConstraints(maxWidth: 300),
+                        child: Padding(
+                          padding: const EdgeInsets.only(left: 8.0),
+                          child: buildDetail(),
+                        ),
+                      ),
+                    ],
+                  ),
+                  const SizedBox(height: 50),
+                ],
+              );
+            }
 
-                // One column
-                return Column(
-                  crossAxisAlignment: CrossAxisAlignment.stretch,
-                  children: [
-                    buildDragHeader(),
-                    buildDate(),
-                    assetWithExif.when(
-                      data: (data) => DescriptionInput(asset: data),
-                      error: (error, stackTrace) => Icon(
-                        Icons.image_not_supported_outlined,
-                        color: context.primaryColor,
-                      ),
-                      loading: () => const SizedBox(
-                        width: 75,
-                        height: 75,
-                        child: CircularProgressIndicator.adaptive(),
-                      ),
-                    ),
-                    buildLocation(),
-                    SizedBox(height: hasCoordinates() ? 16.0 : 6.0),
-                    buildDetail(),
-                    const SizedBox(height: 50),
-                  ],
-                );
-              },
-            ),
-          ),
+            // One column
+            return Column(
+              mainAxisSize: MainAxisSize.min,
+              crossAxisAlignment: CrossAxisAlignment.stretch,
+              children: [
+                buildDate(),
+                assetWithExif.when(
+                  data: (data) => DescriptionInput(asset: data),
+                  error: (error, stackTrace) => Icon(
+                    Icons.image_not_supported_outlined,
+                    color: context.primaryColor,
+                  ),
+                  loading: () => const SizedBox(
+                    width: 75,
+                    height: 75,
+                    child: CircularProgressIndicator.adaptive(),
+                  ),
+                ),
+                buildLocation(),
+                SizedBox(height: hasCoordinates() ? 16.0 : 6.0),
+                buildDetail(),
+                const SizedBox(height: 50),
+              ],
+            );
+          },
         ),
       ),
     );
diff --git a/mobile/lib/modules/asset_viewer/views/gallery_viewer.dart b/mobile/lib/modules/asset_viewer/views/gallery_viewer.dart
index 4c702d4c0a..59dfef8164 100644
--- a/mobile/lib/modules/asset_viewer/views/gallery_viewer.dart
+++ b/mobile/lib/modules/asset_viewer/views/gallery_viewer.dart
@@ -136,6 +136,7 @@ class GalleryViewerPage extends HookConsumerWidget {
         // swallow error silently
         debugPrint('Error precaching next image: $exception, $stackTrace');
       }
+
       if (index < totalAssets && index >= 0) {
         final asset = loadAsset(index);
         precacheImage(
@@ -152,10 +153,11 @@ class GalleryViewerPage extends HookConsumerWidget {
           borderRadius: BorderRadius.all(Radius.circular(15.0)),
         ),
         barrierColor: Colors.transparent,
-        backgroundColor: Colors.transparent,
         isScrollControlled: true,
-        useSafeArea: true,
+        showDragHandle: true,
+        enableDrag: true,
         context: context,
+        useSafeArea: true,
         builder: (context) {
           return Padding(
             padding: EdgeInsets.only(