mirror of
https://github.com/KevinMidboe/immich.git
synced 2025-10-29 17:40:28 +00:00
feat(mobile): Add multi selected assets to album (#1446)
* refactored to use multiple assets in AddToAlbumList * add to album from multiselect * consistent language * fixed accidental boolean
This commit is contained in:
129
mobile/lib/modules/album/ui/add_to_album_bottom_sheet.dart
Normal file
129
mobile/lib/modules/album/ui/add_to_album_bottom_sheet.dart
Normal file
@@ -0,0 +1,129 @@
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
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/asset_selection.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/album/ui/add_to_album_sliverlist.dart';
|
||||
import 'package:immich_mobile/modules/album/ui/album_thumbnail_listtile.dart';
|
||||
import 'package:immich_mobile/routing/router.dart';
|
||||
import 'package:immich_mobile/shared/models/asset.dart';
|
||||
import 'package:immich_mobile/shared/ui/drag_sheet.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_toast.dart';
|
||||
import 'package:openapi/api.dart';
|
||||
|
||||
class AddToAlbumBottomSheet extends HookConsumerWidget {
|
||||
|
||||
/// The asset to add to an album
|
||||
final List<Asset> assets;
|
||||
|
||||
const AddToAlbumBottomSheet({
|
||||
Key? key,
|
||||
required this.assets,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final albums = ref.watch(albumProvider);
|
||||
final albumService = ref.watch(albumServiceProvider);
|
||||
final sharedAlbums = ref.watch(sharedAlbumProvider);
|
||||
|
||||
useEffect(
|
||||
() {
|
||||
// Fetch album updates, e.g., cover image
|
||||
ref.read(albumProvider.notifier).getAllAlbums();
|
||||
ref.read(sharedAlbumProvider.notifier).getAllSharedAlbums();
|
||||
|
||||
return null;
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
void addToAlbum(AlbumResponseDto album) async {
|
||||
final result = await albumService.addAdditionalAssetToAlbum(
|
||||
assets,
|
||||
album.id,
|
||||
);
|
||||
|
||||
if (result != null) {
|
||||
if (result.alreadyInAlbum.isNotEmpty) {
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: 'Already in ${album.albumName}',
|
||||
);
|
||||
} else {
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: 'Added to ${album.albumName}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ref.read(albumProvider.notifier).getAllAlbums();
|
||||
ref.read(sharedAlbumProvider.notifier).getAllSharedAlbums();
|
||||
|
||||
Navigator.pop(context);
|
||||
}
|
||||
|
||||
|
||||
return Card(
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(15),
|
||||
topRight: Radius.circular(15),
|
||||
),
|
||||
),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
sliver: SliverToBoxAdapter(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Align(
|
||||
alignment: Alignment.center,
|
||||
child: CustomDraggingHandle(),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text('Add to album',
|
||||
style: Theme.of(context).textTheme.headline2,
|
||||
),
|
||||
TextButton.icon(
|
||||
icon: const Icon(Icons.add),
|
||||
label: const Text('Create new album'),
|
||||
onPressed: () {
|
||||
ref.watch(assetSelectionProvider.notifier).removeAll();
|
||||
ref.watch(assetSelectionProvider.notifier).addNewAssets(assets);
|
||||
AutoRouter.of(context).push(
|
||||
CreateAlbumRoute(
|
||||
isSharedAlbum: false,
|
||||
initialAssets: assets,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
sliver: AddToAlbumSliverList(
|
||||
albums: albums,
|
||||
sharedAlbums: sharedAlbums,
|
||||
onAddToAlbum: addToAlbum,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -16,11 +16,11 @@ import 'package:openapi/api.dart';
|
||||
class AddToAlbumList extends HookConsumerWidget {
|
||||
|
||||
/// The asset to add to an album
|
||||
final Asset asset;
|
||||
final List<Asset> assets;
|
||||
|
||||
const AddToAlbumList({
|
||||
Key? key,
|
||||
required this.asset,
|
||||
required this.assets,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
@@ -42,7 +42,7 @@ class AddToAlbumList extends HookConsumerWidget {
|
||||
|
||||
void addToAlbum(AlbumResponseDto album) async {
|
||||
final result = await albumService.addAdditionalAssetToAlbum(
|
||||
[asset],
|
||||
assets,
|
||||
album.id,
|
||||
);
|
||||
|
||||
@@ -84,22 +84,27 @@ class AddToAlbumList extends HookConsumerWidget {
|
||||
child: CustomDraggingHandle(),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text('Add to album',
|
||||
style: Theme.of(context).textTheme.headline1,
|
||||
),
|
||||
TextButton.icon(
|
||||
icon: const Icon(Icons.add),
|
||||
label: const Text('New album'),
|
||||
onPressed: () {
|
||||
ref.watch(assetSelectionProvider.notifier).removeAll();
|
||||
ref.watch(assetSelectionProvider.notifier).addNewAssets([asset]);
|
||||
AutoRouter.of(context).push(
|
||||
CreateAlbumRoute(
|
||||
isSharedAlbum: false,
|
||||
initialAssets: [asset],
|
||||
),
|
||||
);
|
||||
},
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text('Add to album',
|
||||
style: Theme.of(context).textTheme.headline2,
|
||||
),
|
||||
TextButton.icon(
|
||||
icon: const Icon(Icons.add),
|
||||
label: const Text('New album'),
|
||||
onPressed: () {
|
||||
ref.watch(assetSelectionProvider.notifier).removeAll();
|
||||
ref.watch(assetSelectionProvider.notifier).addNewAssets(assets);
|
||||
AutoRouter.of(context).push(
|
||||
CreateAlbumRoute(
|
||||
isSharedAlbum: false,
|
||||
initialAssets: assets,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
56
mobile/lib/modules/album/ui/add_to_album_sliverlist.dart
Normal file
56
mobile/lib/modules/album/ui/add_to_album_sliverlist.dart
Normal file
@@ -0,0 +1,56 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/modules/album/ui/album_thumbnail_listtile.dart';
|
||||
import 'package:openapi/api.dart';
|
||||
|
||||
class AddToAlbumSliverList extends HookConsumerWidget {
|
||||
|
||||
/// The asset to add to an album
|
||||
final List<AlbumResponseDto> albums;
|
||||
final List<AlbumResponseDto> sharedAlbums;
|
||||
final void Function(AlbumResponseDto) onAddToAlbum;
|
||||
|
||||
const AddToAlbumSliverList({
|
||||
Key? key,
|
||||
required this.onAddToAlbum,
|
||||
required this.albums,
|
||||
required this.sharedAlbums,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
return SliverList(
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
childCount: albums.length + (sharedAlbums.isEmpty ? 0 : 1),
|
||||
(context, index) {
|
||||
// Build shared expander
|
||||
if (index == 0 && sharedAlbums.isNotEmpty) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8),
|
||||
child: ExpansionTile(
|
||||
title: const Text('Shared'),
|
||||
tilePadding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
leading: const Icon(Icons.group),
|
||||
children: sharedAlbums.map((album) =>
|
||||
AlbumThumbnailListTile(
|
||||
album: album,
|
||||
onTap: () => onAddToAlbum(album),
|
||||
),
|
||||
).toList(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Build albums list
|
||||
final offset = index - (sharedAlbums.isNotEmpty ? 1 : 0);
|
||||
final album = albums[offset];
|
||||
return AlbumThumbnailListTile(
|
||||
album: album,
|
||||
onTap: () => onAddToAlbum(album),
|
||||
);
|
||||
}
|
||||
),
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user