control_bottom_app_bar.dart 7.6 KB

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