1
0
mirror of https://github.com/immich-app/immich.git synced 2024-12-26 10:50:29 +02:00

Move selection logic to asset grid class

This commit is contained in:
Matthias Rupp 2022-10-01 19:19:40 +02:00
parent 347ac70063
commit a117e897ca
6 changed files with 354 additions and 328 deletions

View File

@ -8,11 +8,17 @@ class DailyTitleText extends ConsumerWidget {
const DailyTitleText({ const DailyTitleText({
Key? key, Key? key,
required this.isoDate, required this.isoDate,
required this.assetGroup, required this.multiselectEnabled,
required this.onSelect,
required this.onDeselect,
required this.selected,
}) : super(key: key); }) : super(key: key);
final String isoDate; final String isoDate;
final List<AssetResponseDto> assetGroup; final bool multiselectEnabled;
final Function onSelect;
final Function onDeselect;
final bool selected;
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
@ -23,51 +29,12 @@ class DailyTitleText extends ConsumerWidget {
: "daily_title_text_date_year".tr(); : "daily_title_text_date_year".tr();
var dateText = var dateText =
DateFormat(formatDateTemplate).format(DateTime.parse(isoDate)); DateFormat(formatDateTemplate).format(DateTime.parse(isoDate));
var isMultiSelectEnable =
ref.watch(homePageStateProvider).isMultiSelectEnable;
var selectedDateGroup = ref.watch(homePageStateProvider).selectedDateGroup;
var selectedItems = ref.watch(homePageStateProvider).selectedItems;
void _handleTitleIconClick() { void handleTitleIconClick() {
if (isMultiSelectEnable && if (selected) {
selectedDateGroup.contains(dateText) && onDeselect();
selectedDateGroup.length == 1 &&
selectedItems.length <= assetGroup.length) {
// Multi select is active - click again on the icon while it is the only active group -> disable multi select
ref.watch(homePageStateProvider.notifier).disableMultiSelect();
} else if (isMultiSelectEnable &&
selectedDateGroup.contains(dateText) &&
selectedItems.length != assetGroup.length) {
// Multi select is active - click again on the icon while it is not the only active group -> remove that group from selected group/items
ref
.watch(homePageStateProvider.notifier)
.removeSelectedDateGroup(dateText);
ref
.watch(homePageStateProvider.notifier)
.removeMultipleSelectedItem(assetGroup);
} else if (isMultiSelectEnable &&
selectedDateGroup.contains(dateText) &&
selectedDateGroup.length > 1) {
ref
.watch(homePageStateProvider.notifier)
.removeSelectedDateGroup(dateText);
ref
.watch(homePageStateProvider.notifier)
.removeMultipleSelectedItem(assetGroup);
} else if (isMultiSelectEnable && !selectedDateGroup.contains(dateText)) {
ref
.watch(homePageStateProvider.notifier)
.addSelectedDateGroup(dateText);
ref
.watch(homePageStateProvider.notifier)
.addMultipleSelectedItems(assetGroup);
} else { } else {
ref onSelect();
.watch(homePageStateProvider.notifier)
.enableMultiSelect(assetGroup.toSet());
ref
.watch(homePageStateProvider.notifier)
.addSelectedDateGroup(dateText);
} }
} }
@ -89,8 +56,8 @@ class DailyTitleText extends ConsumerWidget {
), ),
const Spacer(), const Spacer(),
GestureDetector( GestureDetector(
onTap: _handleTitleIconClick, onTap: handleTitleIconClick,
child: isMultiSelectEnable && selectedDateGroup.contains(dateText) child: multiselectEnabled && selected
? Icon( ? Icon(
Icons.check_circle_rounded, Icons.check_circle_rounded,
color: Theme.of(context).primaryColor, color: Theme.of(context).primaryColor,

View File

@ -1,40 +1,36 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
class DisableMultiSelectButton extends ConsumerWidget { class DisableMultiSelectButton extends ConsumerWidget {
const DisableMultiSelectButton({ const DisableMultiSelectButton({
Key? key, Key? key,
required this.onPressed, required this.onPressed,
required this.selectedItemCount, required this.selectedItemCount,
}) : super(key: key); }) : super(key: key);
final Function onPressed; final Function onPressed;
final int selectedItemCount; final int selectedItemCount;
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
return Positioned( return Padding(
top: 10, padding: const EdgeInsets.only(left: 16.0, top: 15),
left: 0, child: Padding(
child: Padding( padding: const EdgeInsets.symmetric(horizontal: 4.0),
padding: const EdgeInsets.only(left: 16.0, top: 46), child: ElevatedButton.icon(
child: Padding( onPressed: () {
padding: const EdgeInsets.symmetric(horizontal: 4.0), onPressed();
child: ElevatedButton.icon( },
onPressed: () { icon: const Icon(Icons.close_rounded),
onPressed(); label: Text(
}, '$selectedItemCount',
icon: const Icon(Icons.close_rounded), style: const TextStyle(
label: Text( fontWeight: FontWeight.w600,
'$selectedItemCount', fontSize: 18,
style: const TextStyle( ),
fontWeight: FontWeight.w600, ),
fontSize: 18, ),
), ),
), );
), }
), }
),
);
}
}

View File

@ -1,3 +1,4 @@
import 'dart:collection';
import 'dart:math'; import 'dart:math';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
@ -5,35 +6,27 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/framework.dart'; import 'package:flutter/src/widgets/framework.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:immich_mobile/modules/home/ui/asset_grid/thumbnail_image.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/modules/home/ui/thumbnail_image.dart';
import 'package:openapi/api.dart'; import 'package:openapi/api.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
import 'asset_grid_data_structure.dart'; import 'asset_grid_data_structure.dart';
import 'daily_title_text.dart'; import 'daily_title_text.dart';
import 'disable_multi_select_button.dart';
import 'draggable_scrollbar_custom.dart'; import 'draggable_scrollbar_custom.dart';
class ImmichAssetGrid extends HookConsumerWidget { typedef ImmichAssetGridSelectionListener = void Function(bool);
class ImmichAssetGridState extends State<ImmichAssetGrid> {
final ItemScrollController _itemScrollController = ItemScrollController(); final ItemScrollController _itemScrollController = ItemScrollController();
final ItemPositionsListener _itemPositionsListener = final ItemPositionsListener _itemPositionsListener =
ItemPositionsListener.create(); ItemPositionsListener.create();
final List<RenderAssetGridElement> renderList; bool _scrolling = false;
final int assetsPerRow; bool _multiselect = false;
final double margin; Set<String> _selectedAssets = HashSet();
final bool showStorageIndicator;
ImmichAssetGrid({
super.key,
required this.renderList,
required this.assetsPerRow,
required this.showStorageIndicator,
this.margin = 5.0,
});
List<AssetResponseDto> get _assets { List<AssetResponseDto> get _assets {
return renderList return widget.renderList
.map((e) { .map((e) {
if (e.type == RenderAssetGridElementType.assetRow) { if (e.type == RenderAssetGridElementType.assetRow) {
return e.assetRow!.assets; return e.assetRow!.assets;
@ -44,10 +37,49 @@ class ImmichAssetGrid extends HookConsumerWidget {
.flattened .flattened
.toList(); .toList();
} }
void _selectAssets(List<AssetResponseDto> assets) {
setState(() {
if (!_multiselect) {
_multiselect = true;
widget.listener?.call(true);
}
for (var e in assets) {
_selectedAssets.add(e.id);
}
});
}
void _deselectAssets(List<AssetResponseDto> assets) {
setState(() {
for (var e in assets) {
_selectedAssets.remove(e.id);
}
if (_selectedAssets.isEmpty) {
_multiselect = false;
widget.listener?.call(false);
}
});
}
void _deselectAll() {
setState(() {
_multiselect = false;
_selectedAssets.clear();
});
widget.listener?.call(false);
}
bool _allAssetsSelected(List<AssetResponseDto> assets) {
return _multiselect && assets.firstWhereOrNull((e) => !_selectedAssets.contains(e.id)) == null;
}
double _getItemSize(BuildContext context) { double _getItemSize(BuildContext context) {
return MediaQuery.of(context).size.width / assetsPerRow - return MediaQuery.of(context).size.width / widget.assetsPerRow -
margin * (assetsPerRow - 1) / assetsPerRow; widget.margin * (widget.assetsPerRow - 1) / widget.assetsPerRow;
} }
Widget _buildThumbnailOrPlaceholder( Widget _buildThumbnailOrPlaceholder(
@ -60,7 +92,10 @@ class ImmichAssetGrid extends HookConsumerWidget {
return ThumbnailImage( return ThumbnailImage(
asset: asset, asset: asset,
assetList: _assets, assetList: _assets,
showStorageIndicator: showStorageIndicator, multiselectEnabled: _multiselect,
isSelected: _selectedAssets.contains(asset.id),
onSelect: () => _selectAssets([asset]),
onDeselect: () => _deselectAssets([asset]),
useGrayBoxPlaceholder: true, useGrayBoxPlaceholder: true,
); );
} }
@ -78,7 +113,7 @@ class ImmichAssetGrid extends HookConsumerWidget {
key: Key("asset-${asset.id}"), key: Key("asset-${asset.id}"),
width: size, width: size,
height: size, height: size,
margin: EdgeInsets.only(top: margin, right: last ? 0.0 : margin), margin: EdgeInsets.only(top: widget.margin, right: last ? 0.0 : widget.margin),
child: _buildThumbnailOrPlaceholder(asset, scrolling), child: _buildThumbnailOrPlaceholder(asset, scrolling),
); );
}).toList(), }).toList(),
@ -89,7 +124,10 @@ class ImmichAssetGrid extends HookConsumerWidget {
BuildContext context, String title, List<AssetResponseDto> assets) { BuildContext context, String title, List<AssetResponseDto> assets) {
return DailyTitleText( return DailyTitleText(
isoDate: title, isoDate: title,
assetGroup: assets, multiselectEnabled: _multiselect,
onSelect: () => _selectAssets(assets),
onDeselect: () => _deselectAssets(assets),
selected: _allAssetsSelected(assets),
); );
} }
@ -111,22 +149,22 @@ class ImmichAssetGrid extends HookConsumerWidget {
); );
} }
Widget _itemBuilder(BuildContext c, int position, bool scrolling) { Widget _itemBuilder(BuildContext c, int position) {
final item = renderList[position]; final item = widget.renderList[position];
if (item.type == RenderAssetGridElementType.dayTitle) { if (item.type == RenderAssetGridElementType.dayTitle) {
return _buildTitle(c, item.title!, item.relatedAssetList!); return _buildTitle(c, item.title!, item.relatedAssetList!);
} else if (item.type == RenderAssetGridElementType.monthTitle) { } else if (item.type == RenderAssetGridElementType.monthTitle) {
return _buildMonthTitle(c, item.title!); return _buildMonthTitle(c, item.title!);
} else if (item.type == RenderAssetGridElementType.assetRow) { } else if (item.type == RenderAssetGridElementType.assetRow) {
return _buildAssetRow(c, item.assetRow!, scrolling); return _buildAssetRow(c, item.assetRow!, _scrolling);
} }
return const Text("Invalid widget type!"); return const Text("Invalid widget type!");
} }
Text _labelBuilder(int pos) { Text _labelBuilder(int pos) {
final date = renderList[pos].date; final date = widget.renderList[pos].date;
return Text(DateFormat.yMMMd().format(date), return Text(DateFormat.yMMMd().format(date),
style: const TextStyle( style: const TextStyle(
color: Colors.white, color: Colors.white,
@ -135,26 +173,27 @@ class ImmichAssetGrid extends HookConsumerWidget {
); );
} }
Widget _buildMultiSelectIndicator() {
return DisableMultiSelectButton(
onPressed: () => _deselectAll(),
selectedItemCount: _selectedAssets.length,
);
}
@override Widget _buildAssetGrid() {
Widget build(BuildContext context, WidgetRef ref) {
final scrolling = useState(false);
final useDragScrolling = _assets.length > 100; final useDragScrolling = _assets.length > 100;
void dragScrolling(bool active) { void dragScrolling(bool active) {
scrolling.value = active; setState(() {
} _scrolling = active;
});
Widget itemBuilder(BuildContext c, int position) {
return _itemBuilder(c, position, scrolling.value);
} }
final listWidget = ScrollablePositionedList.builder( final listWidget = ScrollablePositionedList.builder(
itemBuilder: itemBuilder, itemBuilder: _itemBuilder,
itemPositionsListener: _itemPositionsListener, itemPositionsListener: _itemPositionsListener,
itemScrollController: _itemScrollController, itemScrollController: _itemScrollController,
itemCount: renderList.length, itemCount: widget.renderList.length,
); );
if (!useDragScrolling) { if (!useDragScrolling) {
@ -162,15 +201,48 @@ class ImmichAssetGrid extends HookConsumerWidget {
} }
return DraggableScrollbar.semicircle( return DraggableScrollbar.semicircle(
scrollStateListener: dragScrolling, scrollStateListener: dragScrolling,
itemPositionsListener: _itemPositionsListener, itemPositionsListener: _itemPositionsListener,
controller: _itemScrollController, controller: _itemScrollController,
backgroundColor: Theme.of(context).hintColor, backgroundColor: Theme.of(context).hintColor,
labelTextBuilder: _labelBuilder, labelTextBuilder: _labelBuilder,
labelConstraints: const BoxConstraints(maxHeight: 28), labelConstraints: const BoxConstraints(maxHeight: 28),
scrollbarAnimationDuration: const Duration(seconds: 1), scrollbarAnimationDuration: const Duration(seconds: 1),
scrollbarTimeToFade: const Duration(seconds: 4), scrollbarTimeToFade: const Duration(seconds: 4),
child: listWidget, child: listWidget,
);
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
_buildAssetGrid(),
if (_multiselect) _buildMultiSelectIndicator(),
],
); );
} }
} }
class ImmichAssetGrid extends StatefulWidget {
final List<RenderAssetGridElement> renderList;
final int assetsPerRow;
final double margin;
final bool showStorageIndicator;
final ImmichAssetGridSelectionListener? listener;
ImmichAssetGrid({
super.key,
required this.renderList,
required this.assetsPerRow,
required this.showStorageIndicator,
this.listener,
this.margin = 5.0,
});
@override
State<StatefulWidget> createState() {
return ImmichAssetGridState();
}
}

View File

@ -1,176 +1,174 @@
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart'; import 'package:collection/collection.dart';
import 'package:flutter/services.dart'; import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart'; import 'package:flutter/services.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hive_flutter/hive_flutter.dart';
import 'package:immich_mobile/constants/hive_box.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/modules/home/providers/home_page_state.provider.dart'; import 'package:immich_mobile/constants/hive_box.dart';
import 'package:immich_mobile/modules/login/providers/authentication.provider.dart'; import 'package:immich_mobile/modules/home/providers/home_page_state.provider.dart';
import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/modules/login/providers/authentication.provider.dart';
import 'package:immich_mobile/utils/image_url_builder.dart'; import 'package:immich_mobile/routing/router.dart';
import 'package:openapi/api.dart'; import 'package:immich_mobile/utils/image_url_builder.dart';
import 'package:openapi/api.dart';
class ThumbnailImage extends HookConsumerWidget {
final AssetResponseDto asset; class ThumbnailImage extends HookConsumerWidget {
final List<AssetResponseDto> assetList; final AssetResponseDto asset;
final bool showStorageIndicator; final List<AssetResponseDto> assetList;
final bool useGrayBoxPlaceholder; final bool showStorageIndicator;
final bool useGrayBoxPlaceholder;
const ThumbnailImage({ final bool isSelected;
Key? key, final bool multiselectEnabled;
required this.asset, final Function? onSelect;
required this.assetList, final Function? onDeselect;
this.showStorageIndicator = true,
this.useGrayBoxPlaceholder = false, const ThumbnailImage({
}) : super(key: key); Key? key,
required this.asset,
@override required this.assetList,
Widget build(BuildContext context, WidgetRef ref) { this.showStorageIndicator = true,
var box = Hive.box(userInfoBox); this.useGrayBoxPlaceholder = false,
var thumbnailRequestUrl = getThumbnailUrl(asset); this.isSelected = false,
var selectedAsset = ref.watch(homePageStateProvider).selectedItems; this.multiselectEnabled = false,
var isMultiSelectEnable = this.onDeselect,
ref.watch(homePageStateProvider).isMultiSelectEnable; this.onSelect,
var deviceId = ref.watch(authenticationProvider).deviceId; }) : super(key: key);
Widget buildSelectionIcon(AssetResponseDto asset) { @override
if (selectedAsset.contains(asset)) { Widget build(BuildContext context, WidgetRef ref) {
return Icon( var box = Hive.box(userInfoBox);
Icons.check_circle, var thumbnailRequestUrl = getThumbnailUrl(asset);
color: Theme.of(context).primaryColor, var deviceId = ref.watch(authenticationProvider).deviceId;
);
} else {
return const Icon( Widget buildSelectionIcon(AssetResponseDto asset) {
Icons.circle_outlined, if (isSelected) {
color: Colors.white, return Icon(
); Icons.check_circle,
} color: Theme.of(context).primaryColor,
} );
} else {
return GestureDetector( return const Icon(
onTap: () { Icons.circle_outlined,
if (isMultiSelectEnable && color: Colors.white,
selectedAsset.contains(asset) && );
selectedAsset.length == 1) { }
ref.watch(homePageStateProvider.notifier).disableMultiSelect(); }
} else if (isMultiSelectEnable &&
selectedAsset.contains(asset) && return GestureDetector(
selectedAsset.length > 1) { onTap: () {
ref if (multiselectEnabled) {
.watch(homePageStateProvider.notifier) if (isSelected) {
.removeSingleSelectedItem(asset); onDeselect?.call();
} else if (isMultiSelectEnable && !selectedAsset.contains(asset)) { } else {
ref onSelect?.call();
.watch(homePageStateProvider.notifier) }
.addSingleSelectedItem(asset); } else {
} else { AutoRouter.of(context).push(
AutoRouter.of(context).push( GalleryViewerRoute(
GalleryViewerRoute( assetList: assetList,
assetList: assetList, asset: asset,
asset: asset, ),
), );
); }
} },
}, onLongPress: () {
onLongPress: () { onSelect?.call();
// Enable multi select function HapticFeedback.heavyImpact();
ref.watch(homePageStateProvider.notifier).enableMultiSelect({asset}); },
HapticFeedback.heavyImpact(); child: Hero(
}, tag: asset.id,
child: Hero( child: Stack(
tag: asset.id, children: [
child: Stack( Container(
children: [ decoration: BoxDecoration(
Container( border: multiselectEnabled && isSelected
decoration: BoxDecoration( ? Border.all(
border: isMultiSelectEnable && selectedAsset.contains(asset) color: Theme.of(context).primaryColorLight,
? Border.all( width: 10,
color: Theme.of(context).primaryColorLight, )
width: 10, : const Border(),
) ),
: const Border(), child: CachedNetworkImage(
), cacheKey: 'thumbnail-image-${asset.id}',
child: CachedNetworkImage( width: 300,
cacheKey: 'thumbnail-image-${asset.id}', height: 300,
width: 300, memCacheHeight: 200,
height: 300, maxWidthDiskCache: 200,
memCacheHeight: 200, maxHeightDiskCache: 200,
maxWidthDiskCache: 200, fit: BoxFit.cover,
maxHeightDiskCache: 200, imageUrl: thumbnailRequestUrl,
fit: BoxFit.cover, httpHeaders: {
imageUrl: thumbnailRequestUrl, "Authorization": "Bearer ${box.get(accessTokenKey)}"
httpHeaders: { },
"Authorization": "Bearer ${box.get(accessTokenKey)}" fadeInDuration: const Duration(milliseconds: 250),
}, progressIndicatorBuilder: (context, url, downloadProgress) {
fadeInDuration: const Duration(milliseconds: 250), if (useGrayBoxPlaceholder) {
progressIndicatorBuilder: (context, url, downloadProgress) { return const DecoratedBox(
if (useGrayBoxPlaceholder) { decoration: BoxDecoration(color: Colors.grey),
return const DecoratedBox( );
decoration: BoxDecoration(color: Colors.grey), }
); return Transform.scale(
} scale: 0.2,
return Transform.scale( child: CircularProgressIndicator(
scale: 0.2, value: downloadProgress.progress,
child: CircularProgressIndicator( ),
value: downloadProgress.progress, );
), },
); errorWidget: (context, url, error) {
}, debugPrint("Error getting thumbnail $url = $error");
errorWidget: (context, url, error) { CachedNetworkImage.evictFromCache(thumbnailRequestUrl);
debugPrint("Error getting thumbnail $url = $error");
CachedNetworkImage.evictFromCache(thumbnailRequestUrl); return Icon(
Icons.image_not_supported_outlined,
return Icon( color: Theme.of(context).primaryColor,
Icons.image_not_supported_outlined, );
color: Theme.of(context).primaryColor, },
); ),
}, ),
), if (multiselectEnabled)
), Padding(
if (isMultiSelectEnable) padding: const EdgeInsets.all(3.0),
Padding( child: Align(
padding: const EdgeInsets.all(3.0), alignment: Alignment.topLeft,
child: Align( child: buildSelectionIcon(asset),
alignment: Alignment.topLeft, ),
child: buildSelectionIcon(asset), ),
), if (showStorageIndicator)
), Positioned(
if (showStorageIndicator) right: 10,
Positioned( bottom: 5,
right: 10, child: Icon(
bottom: 5, (deviceId != asset.deviceId)
child: Icon( ? Icons.cloud_done_outlined
(deviceId != asset.deviceId) : Icons.photo_library_rounded,
? Icons.cloud_done_outlined color: Colors.white,
: Icons.photo_library_rounded, size: 18,
color: Colors.white, ),
size: 18, ),
), if (asset.type != AssetTypeEnum.IMAGE)
), Positioned(
if (asset.type != AssetTypeEnum.IMAGE) top: 5,
Positioned( right: 5,
top: 5, child: Row(
right: 5, children: [
child: Row( Text(
children: [ asset.duration.toString().substring(0, 7),
Text( style: const TextStyle(
asset.duration.toString().substring(0, 7), color: Colors.white,
style: const TextStyle( fontSize: 10,
color: Colors.white, ),
fontSize: 10, ),
), const Icon(
), Icons.play_circle_outline_rounded,
const Icon( color: Colors.white,
Icons.play_circle_outline_rounded, ),
color: Colors.white, ],
), ),
], ),
), ],
), ),
], ),
), );
), }
); }
}
}

View File

@ -1,6 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/modules/home/ui/thumbnail_image.dart'; import 'package:immich_mobile/modules/home/ui/asset_grid/thumbnail_image.dart';
import 'package:openapi/api.dart'; import 'package:openapi/api.dart';
// ignore: must_be_immutable // ignore: must_be_immutable

View File

@ -5,7 +5,6 @@ import 'package:immich_mobile/modules/home/providers/home_page_render_list_provi
import 'package:immich_mobile/modules/home/providers/home_page_state.provider.dart'; import 'package:immich_mobile/modules/home/providers/home_page_state.provider.dart';
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart'; import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart';
import 'package:immich_mobile/modules/home/ui/control_bottom_app_bar.dart'; import 'package:immich_mobile/modules/home/ui/control_bottom_app_bar.dart';
import 'package:immich_mobile/modules/home/ui/disable_multi_select_button.dart';
import 'package:immich_mobile/modules/home/ui/immich_sliver_appbar.dart'; import 'package:immich_mobile/modules/home/ui/immich_sliver_appbar.dart';
import 'package:immich_mobile/modules/home/ui/profile_drawer/profile_drawer.dart'; import 'package:immich_mobile/modules/home/ui/profile_drawer/profile_drawer.dart';
import 'package:immich_mobile/modules/settings/providers/app_settings.provider.dart'; import 'package:immich_mobile/modules/settings/providers/app_settings.provider.dart';
@ -20,12 +19,9 @@ class HomePage extends HookConsumerWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final appSettingService = ref.watch(appSettingsServiceProvider); final appSettingService = ref.watch(appSettingsServiceProvider);
var renderList = ref.watch(renderListProvider); var renderList = ref.watch(renderListProvider);
var isMultiSelectEnable = final multiselectEnabled = useState(false);
ref.watch(homePageStateProvider).isMultiSelectEnable;
var homePageState = ref.watch(homePageStateProvider);
useEffect( useEffect(
() { () {
@ -41,16 +37,9 @@ class HomePage extends HookConsumerWidget {
ref.read(assetProvider.notifier).getAllAsset(); ref.read(assetProvider.notifier).getAllAsset();
} }
buildSelectedItemCountIndicator() {
return DisableMultiSelectButton(
onPressed: ref.watch(homePageStateProvider.notifier).disableMultiSelect,
selectedItemCount: homePageState.selectedItems.length,
);
}
Widget buildBody() { Widget buildBody() {
buildSliverAppBar() { buildSliverAppBar() {
return isMultiSelectEnable return multiselectEnabled.value
? const SliverToBoxAdapter( ? const SliverToBoxAdapter(
child: SizedBox( child: SizedBox(
height: 70, height: 70,
@ -62,9 +51,13 @@ class HomePage extends HookConsumerWidget {
); );
} }
void selectionListener(bool multiselect) {
multiselectEnabled.value = multiselect;
}
return SafeArea( return SafeArea(
bottom: !isMultiSelectEnable, bottom: !multiselectEnabled.value,
top: !isMultiSelectEnable, top: !multiselectEnabled.value,
child: Stack( child: Stack(
children: [ children: [
CustomScrollView( CustomScrollView(
@ -80,10 +73,10 @@ class HomePage extends HookConsumerWidget {
appSettingService.getSetting(AppSettingsEnum.tilesPerRow), appSettingService.getSetting(AppSettingsEnum.tilesPerRow),
showStorageIndicator: appSettingService showStorageIndicator: appSettingService
.getSetting(AppSettingsEnum.storageIndicator), .getSetting(AppSettingsEnum.storageIndicator),
listener: selectionListener,
), ),
), ),
if (isMultiSelectEnable) ...[ if (multiselectEnabled.value) ...[
buildSelectedItemCountIndicator(),
const ControlBottomAppBar(), const ControlBottomAppBar(),
], ],
], ],