Bladeren bron

feat(mobile) Enhance bottom app bar on home page (#934)

* Added bottom sheet

* Finished styling bottom app bar

* Fixed border radius
Alex 2 jaren geleden
bovenliggende
commit
f0874ff3fd
2 gewijzigde bestanden met toevoegingen van 180 en 121 verwijderingen
  1. 170 112
      mobile/lib/modules/home/ui/control_bottom_app_bar.dart
  2. 10 9
      mobile/lib/modules/home/views/home_page.dart

+ 170 - 112
mobile/lib/modules/home/ui/control_bottom_app_bar.dart

@@ -28,34 +28,30 @@ class ControlBottomAppBar extends ConsumerWidget {
   @override
   Widget build(BuildContext context, WidgetRef ref) {
     Widget renderActionButtons() {
-      return Padding(
-        padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20),
-        child: Row(
-          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
-          children: [
-            ControlBoxButton(
-              iconData: Icons.delete_forever_rounded,
-              label: "control_bottom_app_bar_delete".tr(),
-              onPressed: () {
-                showDialog(
-                  context: context,
-                  builder: (BuildContext context) {
-                    return DeleteDialog(
-                      onDelete: onDelete,
-                    );
-                  },
-                );
-              },
-            ),
-            ControlBoxButton(
-              iconData: Icons.share,
-              label: "control_bottom_app_bar_share".tr(),
-              onPressed: () {
-                onShare();
-              },
-            ),
-          ],
-        ),
+      return Row(
+        children: [
+          ControlBoxButton(
+            iconData: Icons.ios_share_rounded,
+            label: "control_bottom_app_bar_share".tr(),
+            onPressed: () {
+              onShare();
+            },
+          ),
+          ControlBoxButton(
+            iconData: Icons.delete_outline_rounded,
+            label: "control_bottom_app_bar_delete".tr(),
+            onPressed: () {
+              showDialog(
+                context: context,
+                builder: (BuildContext context) {
+                  return DeleteDialog(
+                    onDelete: onDelete,
+                  );
+                },
+              );
+            },
+          ),
+        ],
       );
     }
 
@@ -63,40 +59,44 @@ class ControlBottomAppBar extends ConsumerWidget {
       Widget renderAlbum(AlbumResponseDto album) {
         final box = Hive.box(userInfoBox);
 
-        return GestureDetector(
-          onTap: () => onAddToAlbum(album),
-          child: Container(
-            width: 112,
-            padding: const EdgeInsets.all(6),
-            child: Column(
-              crossAxisAlignment: CrossAxisAlignment.start,
-              children: [
-                ClipRRect(
-                  borderRadius: BorderRadius.circular(8),
-                  child: CachedNetworkImage(
-                    width: 100,
-                    height: 100,
-                    fit: BoxFit.cover,
-                    imageUrl:
-                        getAlbumThumbnailUrl(album, type: ThumbnailFormat.JPEG),
-                    httpHeaders: {
-                      "Authorization": "Bearer ${box.get(accessTokenKey)}"
-                    },
-                    cacheKey: "${album.albumThumbnailAssetId}",
+        return Padding(
+          padding: const EdgeInsets.only(left: 8.0),
+          child: GestureDetector(
+            onTap: () => onAddToAlbum(album),
+            child: Container(
+              width: 112,
+              padding: const EdgeInsets.all(6),
+              child: Column(
+                crossAxisAlignment: CrossAxisAlignment.start,
+                children: [
+                  ClipRRect(
+                    borderRadius: BorderRadius.circular(8),
+                    child: CachedNetworkImage(
+                      width: 100,
+                      height: 100,
+                      fit: BoxFit.cover,
+                      imageUrl: getAlbumThumbnailUrl(
+                        album,
+                        type: ThumbnailFormat.JPEG,
+                      ),
+                      httpHeaders: {
+                        "Authorization": "Bearer ${box.get(accessTokenKey)}"
+                      },
+                      cacheKey: "${album.albumThumbnailAssetId}",
+                    ),
                   ),
-                ),
-                Padding(
-                  padding: const EdgeInsets.only(top: 12),
-                  child: Text(
-                    album.albumName,
-                    style: TextStyle(fontWeight: FontWeight.bold),
+                  Padding(
+                    padding: const EdgeInsets.only(top: 12),
+                    child: Text(
+                      album.albumName,
+                      style: const TextStyle(
+                        fontWeight: FontWeight.bold,
+                        fontSize: 12.0,
+                      ),
+                    ),
                   ),
-                ),
-                Text(album.shared
-                        ? "control_bottom_app_bar_album_info_shared"
-                        : "control_bottom_app_bar_album_info")
-                    .tr(args: [album.assetCount.toString()]),
-              ],
+                ],
+              ),
             ),
           ),
         );
@@ -112,52 +112,109 @@ class ControlBottomAppBar extends ConsumerWidget {
       );
     }
 
-    return Positioned(
-      bottom: 0,
-      left: 0,
-      child: Container(
-        width: MediaQuery.of(context).size.width,
-        decoration: BoxDecoration(
-          borderRadius: const BorderRadius.only(
-            topLeft: Radius.circular(10),
-            topRight: Radius.circular(10),
+    return DraggableScrollableSheet(
+      initialChildSize: 0.30,
+      minChildSize: 0.15,
+      maxChildSize: 0.57,
+      snap: true,
+      builder: (
+        BuildContext context,
+        ScrollController scrollController,
+      ) {
+        return SingleChildScrollView(
+          controller: scrollController,
+          child: Card(
+            elevation: 12.0,
+            shape: const RoundedRectangleBorder(
+              borderRadius: BorderRadius.only(
+                topLeft: Radius.circular(12),
+                topRight: Radius.circular(12),
+              ),
+            ),
+            margin: const EdgeInsets.all(0),
+            child: Container(
+              decoration: const BoxDecoration(
+                borderRadius: BorderRadius.only(
+                  topLeft: Radius.circular(12),
+                  topRight: Radius.circular(12),
+                ),
+              ),
+              child: Column(
+                children: <Widget>[
+                  const SizedBox(height: 12),
+                  const CustomDraggingHandle(),
+                  const SizedBox(height: 12),
+                  renderActionButtons(),
+                  const Divider(
+                    indent: 16,
+                    endIndent: 16,
+                    thickness: 1,
+                  ),
+                  AddToAlbumTitleRow(
+                    onCreateNewAlbum: () => onCreateNewAlbum(),
+                  ),
+                  renderAlbums(),
+                  const SizedBox(height: 12),
+                ],
+              ),
+            ),
           ),
-          color: Theme.of(context).scaffoldBackgroundColor,
-        ),
-        child: Column(
-          crossAxisAlignment: CrossAxisAlignment.start,
-          children: [
-            renderActionButtons(),
-            const Divider(
-              thickness: 2,
+        );
+      },
+    );
+  }
+}
+
+class AddToAlbumTitleRow extends StatelessWidget {
+  const AddToAlbumTitleRow({
+    super.key,
+    required this.onCreateNewAlbum,
+  });
+
+  final VoidCallback onCreateNewAlbum;
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: const EdgeInsets.symmetric(horizontal: 16),
+      child: Row(
+        mainAxisAlignment: MainAxisAlignment.spaceBetween,
+        children: [
+          const Text(
+            "control_bottom_app_bar_add_to_album",
+            style: TextStyle(
+              fontSize: 14,
+              fontWeight: FontWeight.bold,
             ),
-            Padding(
-                padding: const EdgeInsets.all(12),
-                child: Row(
-                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
-                  children: [
-                    const Text(
-                      "control_bottom_app_bar_add_to_album",
-                      style: TextStyle(
-                        fontSize: 16,
-                        fontWeight: FontWeight.bold,
-                      ),
-                    ).tr(),
-                    TextButton(
-                      onPressed: onCreateNewAlbum,
-                      child: Text(
-                        "control_bottom_app_bar_create_new_album",
-                        style: TextStyle(
-                          color: Theme.of(context).primaryColor,
-                          fontWeight: FontWeight.bold,
-                        ),
-                      ).tr(),
-                    ),
-                  ],
-                )),
-            renderAlbums(),
-          ],
-        ),
+          ).tr(),
+          TextButton(
+            onPressed: onCreateNewAlbum,
+            child: Text(
+              "control_bottom_app_bar_create_new_album",
+              style: TextStyle(
+                color: Theme.of(context).primaryColor,
+                fontWeight: FontWeight.bold,
+                fontSize: 14,
+              ),
+            ).tr(),
+          ),
+        ],
+      ),
+    );
+  }
+}
+
+class CustomDraggingHandle extends StatelessWidget {
+  const CustomDraggingHandle({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      height: 5,
+      width: 30,
+      decoration: BoxDecoration(
+        color: Colors.grey[500],
+        borderRadius: BorderRadius.circular(16),
       ),
     );
   }
@@ -177,19 +234,20 @@ class ControlBoxButton extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    return SizedBox(
-      width: 60,
+    return MaterialButton(
+      padding: const EdgeInsets.all(10),
+      shape: const CircleBorder(),
+      onPressed: () => onPressed(),
       child: Column(
         mainAxisAlignment: MainAxisAlignment.start,
         crossAxisAlignment: CrossAxisAlignment.center,
         children: [
-          IconButton(
-            onPressed: () {
-              onPressed();
-            },
-            icon: Icon(iconData, size: 30),
+          Icon(iconData, size: 24),
+          const SizedBox(height: 6),
+          Text(
+            label,
+            style: const TextStyle(fontSize: 12.0),
           ),
-          Text(label)
         ],
       ),
     );

+ 10 - 9
mobile/lib/modules/home/views/home_page.dart

@@ -4,7 +4,6 @@ import 'package:flutter/material.dart';
 import 'package:flutter_hooks/flutter_hooks.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
 import 'package:immich_mobile/modules/album/providers/album.provider.dart';
-import 'package:immich_mobile/modules/album/providers/shared_album.provider.dart';
 import 'package:immich_mobile/modules/album/services/album.service.dart';
 import 'package:immich_mobile/modules/home/providers/home_page_render_list_provider.dart';
 import 'package:immich_mobile/modules/home/providers/multiselect.provider.dart';
@@ -79,10 +78,11 @@ class HomePage extends HookConsumerWidget {
 
       void onAddToAlbum(AlbumResponseDto album) async {
         final result = await albumService.addAdditionalAssetToAlbum(
-            selection.value, album.id);
+          selection.value,
+          album.id,
+        );
 
         if (result != null) {
-
           if (result.alreadyInAlbum.isNotEmpty) {
             ImmichToast.show(
               context: context,
@@ -130,14 +130,16 @@ class HomePage extends HookConsumerWidget {
             CustomScrollView(
               slivers: [
                 if (!multiselectEnabled.state)
-                ImmichSliverAppBar(
-                  onPopBack: reloadAllAsset,
-                ),
+                  ImmichSliverAppBar(
+                    onPopBack: reloadAllAsset,
+                  ),
               ],
             ),
             Padding(
               padding: EdgeInsets.only(
-                  top: selectionEnabledHook.value ? 0 : 60, bottom: 0.0),
+                top: selectionEnabledHook.value ? 0 : 60,
+                bottom: 0.0,
+              ),
               child: ImmichAssetGrid(
                 renderList: renderList,
                 assetsPerRow:
@@ -148,7 +150,7 @@ class HomePage extends HookConsumerWidget {
                 selectionActive: selectionEnabledHook.value,
               ),
             ),
-            if (selectionEnabledHook.value) ...[
+            if (selectionEnabledHook.value)
               ControlBottomAppBar(
                 onShare: onShareAssets,
                 onDelete: onDelete,
@@ -156,7 +158,6 @@ class HomePage extends HookConsumerWidget {
                 albums: albums,
                 onCreateNewAlbum: onCreateNewAlbum,
               ),
-            ],
           ],
         ),
       );