control_bottom_app_bar.dart 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. import 'package:easy_localization/easy_localization.dart';
  2. import 'package:flutter/material.dart';
  3. import 'package:hooks_riverpod/hooks_riverpod.dart';
  4. import 'package:immich_mobile/modules/album/ui/add_to_album_sliverlist.dart';
  5. import 'package:immich_mobile/modules/home/models/selection_state.dart';
  6. import 'package:immich_mobile/modules/home/ui/delete_dialog.dart';
  7. import 'package:immich_mobile/modules/home/ui/upload_dialog.dart';
  8. import 'package:immich_mobile/shared/providers/server_info.provider.dart';
  9. import 'package:immich_mobile/shared/ui/drag_sheet.dart';
  10. import 'package:immich_mobile/shared/models/album.dart';
  11. class ControlBottomAppBar extends ConsumerWidget {
  12. final void Function(bool shareLocal) onShare;
  13. final void Function() onFavorite;
  14. final void Function() onArchive;
  15. final void Function() onDelete;
  16. final Function(Album album) onAddToAlbum;
  17. final void Function() onCreateNewAlbum;
  18. final void Function() onUpload;
  19. final void Function() onStack;
  20. final List<Album> albums;
  21. final List<Album> sharedAlbums;
  22. final bool enabled;
  23. final SelectionAssetState selectionAssetState;
  24. const ControlBottomAppBar({
  25. Key? key,
  26. required this.onShare,
  27. required this.onFavorite,
  28. required this.onArchive,
  29. required this.onDelete,
  30. required this.sharedAlbums,
  31. required this.albums,
  32. required this.onAddToAlbum,
  33. required this.onCreateNewAlbum,
  34. required this.onUpload,
  35. required this.onStack,
  36. this.selectionAssetState = const SelectionAssetState(),
  37. this.enabled = true,
  38. }) : super(key: key);
  39. @override
  40. Widget build(BuildContext context, WidgetRef ref) {
  41. var hasRemote =
  42. selectionAssetState.hasRemote || selectionAssetState.hasMerged;
  43. var hasLocal = selectionAssetState.hasLocal;
  44. final trashEnabled =
  45. ref.watch(serverInfoProvider.select((v) => v.serverFeatures.trash));
  46. List<Widget> renderActionButtons() {
  47. return [
  48. if (hasRemote)
  49. ControlBoxButton(
  50. iconData: Icons.share_rounded,
  51. label: "control_bottom_app_bar_share".tr(),
  52. onPressed: enabled ? () => onShare(false) : null,
  53. ),
  54. ControlBoxButton(
  55. iconData: Icons.ios_share_rounded,
  56. label: "control_bottom_app_bar_share_to".tr(),
  57. onPressed: enabled ? () => onShare(true) : null,
  58. ),
  59. if (hasRemote)
  60. ControlBoxButton(
  61. iconData: Icons.archive,
  62. label: "control_bottom_app_bar_archive".tr(),
  63. onPressed: enabled ? onArchive : null,
  64. ),
  65. if (hasRemote)
  66. ControlBoxButton(
  67. iconData: Icons.favorite_border_rounded,
  68. label: "control_bottom_app_bar_favorite".tr(),
  69. onPressed: enabled ? onFavorite : null,
  70. ),
  71. ControlBoxButton(
  72. iconData: Icons.delete_outline_rounded,
  73. label: "control_bottom_app_bar_delete".tr(),
  74. onPressed: enabled
  75. ? () {
  76. if (!trashEnabled) {
  77. showDialog(
  78. context: context,
  79. builder: (BuildContext context) {
  80. return DeleteDialog(
  81. onDelete: onDelete,
  82. );
  83. },
  84. );
  85. } else {
  86. onDelete();
  87. }
  88. }
  89. : null,
  90. ),
  91. if (!hasLocal && selectionAssetState.selectedCount > 1)
  92. ControlBoxButton(
  93. iconData: Icons.filter_none_rounded,
  94. label: "control_bottom_app_bar_stack".tr(),
  95. onPressed: enabled ? onStack : null,
  96. ),
  97. if (hasLocal)
  98. ControlBoxButton(
  99. iconData: Icons.backup_outlined,
  100. label: "Upload",
  101. onPressed: enabled
  102. ? () => showDialog(
  103. context: context,
  104. builder: (BuildContext context) {
  105. return UploadDialog(
  106. onUpload: onUpload,
  107. );
  108. },
  109. )
  110. : null,
  111. ),
  112. ];
  113. }
  114. return DraggableScrollableSheet(
  115. initialChildSize: hasRemote ? 0.30 : 0.18,
  116. minChildSize: 0.18,
  117. maxChildSize: hasRemote ? 0.60 : 0.18,
  118. snap: true,
  119. builder: (
  120. BuildContext context,
  121. ScrollController scrollController,
  122. ) {
  123. return Card(
  124. elevation: 18.0,
  125. shape: const RoundedRectangleBorder(
  126. borderRadius: BorderRadius.only(
  127. topLeft: Radius.circular(12),
  128. topRight: Radius.circular(12),
  129. ),
  130. ),
  131. margin: const EdgeInsets.all(0),
  132. child: CustomScrollView(
  133. controller: scrollController,
  134. slivers: [
  135. SliverToBoxAdapter(
  136. child: Column(
  137. children: <Widget>[
  138. const SizedBox(height: 12),
  139. const CustomDraggingHandle(),
  140. const SizedBox(height: 12),
  141. SizedBox(
  142. height: 70,
  143. child: ListView(
  144. scrollDirection: Axis.horizontal,
  145. children: renderActionButtons(),
  146. ),
  147. ),
  148. if (hasRemote)
  149. const Divider(
  150. indent: 16,
  151. endIndent: 16,
  152. thickness: 1,
  153. ),
  154. if (hasRemote)
  155. AddToAlbumTitleRow(
  156. onCreateNewAlbum: enabled ? onCreateNewAlbum : null,
  157. ),
  158. ],
  159. ),
  160. ),
  161. if (hasRemote)
  162. SliverPadding(
  163. padding: const EdgeInsets.symmetric(horizontal: 16),
  164. sliver: AddToAlbumSliverList(
  165. albums: albums,
  166. sharedAlbums: sharedAlbums,
  167. onAddToAlbum: onAddToAlbum,
  168. enabled: enabled,
  169. ),
  170. ),
  171. ],
  172. ),
  173. );
  174. },
  175. );
  176. }
  177. }
  178. class AddToAlbumTitleRow extends StatelessWidget {
  179. const AddToAlbumTitleRow({
  180. super.key,
  181. required this.onCreateNewAlbum,
  182. });
  183. final VoidCallback? onCreateNewAlbum;
  184. @override
  185. Widget build(BuildContext context) {
  186. return Padding(
  187. padding: const EdgeInsets.symmetric(horizontal: 16),
  188. child: Row(
  189. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  190. children: [
  191. const Text(
  192. "common_add_to_album",
  193. style: TextStyle(
  194. fontSize: 14,
  195. fontWeight: FontWeight.bold,
  196. ),
  197. ).tr(),
  198. TextButton.icon(
  199. onPressed: onCreateNewAlbum,
  200. icon: Icon(
  201. Icons.add,
  202. color: Theme.of(context).primaryColor,
  203. ),
  204. label: Text(
  205. "common_create_new_album",
  206. style: TextStyle(
  207. color: Theme.of(context).primaryColor,
  208. fontWeight: FontWeight.bold,
  209. fontSize: 14,
  210. ),
  211. ).tr(),
  212. ),
  213. ],
  214. ),
  215. );
  216. }
  217. }