forked from Cutlery/immich
		
	feat(mobile) Enhance bottom app bar on home page (#934)
* Added bottom sheet * Finished styling bottom app bar * Fixed border radius
This commit is contained in:
		
							parent
							
								
									c8538cc62f
								
							
						
					
					
						commit
						f0874ff3fd
					
				@ -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: <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),
 | 
			
		||||
                ],
 | 
			
		||||
              ),
 | 
			
		||||
            ),
 | 
			
		||||
          ),
 | 
			
		||||
        );
 | 
			
		||||
      },
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
        ],
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
@ -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,
 | 
			
		||||
              ),
 | 
			
		||||
            ],
 | 
			
		||||
          ],
 | 
			
		||||
        ),
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user