From f0874ff3fdac9b5dd865c716824552eb65530d1b Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 6 Nov 2022 20:41:10 -0600 Subject: [PATCH] feat(mobile) Enhance bottom app bar on home page (#934) * Added bottom sheet * Finished styling bottom app bar * Fixed border radius --- .../home/ui/control_bottom_app_bar.dart | 284 +++++++++++------- mobile/lib/modules/home/views/home_page.dart | 19 +- 2 files changed, 181 insertions(+), 122 deletions(-) diff --git a/mobile/lib/modules/home/ui/control_bottom_app_bar.dart b/mobile/lib/modules/home/ui/control_bottom_app_bar.dart index 3ad89ac92f..76a85ce925 100644 --- a/mobile/lib/modules/home/ui/control_bottom_app_bar.dart +++ b/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), - ), - color: Theme.of(context).scaffoldBackgroundColor, - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - renderActionButtons(), - const Divider( - thickness: 2, + 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), + ), ), - 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(), - ], - ), + margin: const EdgeInsets.all(0), + child: Container( + decoration: const BoxDecoration( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(12), + topRight: Radius.circular(12), + ), + ), + child: Column( + children: [ + 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), + ], + ), + ), + ), + ); + }, + ); + } +} + +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, + ), + ).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) ], ), ); diff --git a/mobile/lib/modules/home/views/home_page.dart b/mobile/lib/modules/home/views/home_page.dart index 8062fa321a..1b39170ccb 100644 --- a/mobile/lib/modules/home/views/home_page.dart +++ b/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, ), - ], ], ), );