control_bottom_app_bar.dart 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. import 'package:cached_network_image/cached_network_image.dart';
  2. import 'package:easy_localization/easy_localization.dart';
  3. import 'package:flutter/material.dart';
  4. import 'package:hive/hive.dart';
  5. import 'package:hooks_riverpod/hooks_riverpod.dart';
  6. import 'package:immich_mobile/constants/hive_box.dart';
  7. import 'package:immich_mobile/modules/home/ui/delete_diaglog.dart';
  8. import 'package:immich_mobile/utils/image_url_builder.dart';
  9. import 'package:openapi/api.dart';
  10. class ControlBottomAppBar extends ConsumerWidget {
  11. final Function onShare;
  12. final Function onDelete;
  13. final Function(AlbumResponseDto album) onAddToAlbum;
  14. final void Function() onCreateNewAlbum;
  15. final List<AlbumResponseDto> albums;
  16. const ControlBottomAppBar({
  17. Key? key,
  18. required this.onShare,
  19. required this.onDelete,
  20. required this.albums,
  21. required this.onAddToAlbum,
  22. required this.onCreateNewAlbum,
  23. }) : super(key: key);
  24. @override
  25. Widget build(BuildContext context, WidgetRef ref) {
  26. Widget renderActionButtons() {
  27. return Row(
  28. children: [
  29. ControlBoxButton(
  30. iconData: Icons.ios_share_rounded,
  31. label: "control_bottom_app_bar_share".tr(),
  32. onPressed: () {
  33. onShare();
  34. },
  35. ),
  36. ControlBoxButton(
  37. iconData: Icons.delete_outline_rounded,
  38. label: "control_bottom_app_bar_delete".tr(),
  39. onPressed: () {
  40. showDialog(
  41. context: context,
  42. builder: (BuildContext context) {
  43. return DeleteDialog(
  44. onDelete: onDelete,
  45. );
  46. },
  47. );
  48. },
  49. ),
  50. ],
  51. );
  52. }
  53. Widget renderAlbums() {
  54. Widget renderAlbum(AlbumResponseDto album) {
  55. final box = Hive.box(userInfoBox);
  56. return Padding(
  57. padding: const EdgeInsets.only(left: 8.0),
  58. child: GestureDetector(
  59. onTap: () => onAddToAlbum(album),
  60. child: Container(
  61. width: 112,
  62. padding: const EdgeInsets.all(6),
  63. child: Column(
  64. crossAxisAlignment: CrossAxisAlignment.start,
  65. children: [
  66. ClipRRect(
  67. borderRadius: BorderRadius.circular(8),
  68. child: CachedNetworkImage(
  69. width: 100,
  70. height: 100,
  71. fit: BoxFit.cover,
  72. imageUrl: getAlbumThumbnailUrl(album),
  73. httpHeaders: {
  74. "Authorization": "Bearer ${box.get(accessTokenKey)}"
  75. },
  76. cacheKey: getAlbumThumbNailCacheKey(album),
  77. ),
  78. ),
  79. Padding(
  80. padding: const EdgeInsets.only(top: 12),
  81. child: Text(
  82. album.albumName,
  83. style: const TextStyle(
  84. fontWeight: FontWeight.bold,
  85. fontSize: 12.0,
  86. ),
  87. ),
  88. ),
  89. ],
  90. ),
  91. ),
  92. ),
  93. );
  94. }
  95. return SizedBox(
  96. height: 200,
  97. child: ListView.builder(
  98. scrollDirection: Axis.horizontal,
  99. itemBuilder: (buildContext, i) => renderAlbum(albums[i]),
  100. itemCount: albums.length,
  101. ),
  102. );
  103. }
  104. return DraggableScrollableSheet(
  105. initialChildSize: 0.30,
  106. minChildSize: 0.15,
  107. maxChildSize: 0.57,
  108. snap: true,
  109. builder: (
  110. BuildContext context,
  111. ScrollController scrollController,
  112. ) {
  113. return SingleChildScrollView(
  114. controller: scrollController,
  115. child: Card(
  116. elevation: 12.0,
  117. shape: const RoundedRectangleBorder(
  118. borderRadius: BorderRadius.only(
  119. topLeft: Radius.circular(12),
  120. topRight: Radius.circular(12),
  121. ),
  122. ),
  123. margin: const EdgeInsets.all(0),
  124. child: Container(
  125. decoration: const BoxDecoration(
  126. borderRadius: BorderRadius.only(
  127. topLeft: Radius.circular(12),
  128. topRight: Radius.circular(12),
  129. ),
  130. ),
  131. child: Column(
  132. children: <Widget>[
  133. const SizedBox(height: 12),
  134. const CustomDraggingHandle(),
  135. const SizedBox(height: 12),
  136. renderActionButtons(),
  137. const Divider(
  138. indent: 16,
  139. endIndent: 16,
  140. thickness: 1,
  141. ),
  142. AddToAlbumTitleRow(
  143. onCreateNewAlbum: () => onCreateNewAlbum(),
  144. ),
  145. renderAlbums(),
  146. const SizedBox(height: 200),
  147. ],
  148. ),
  149. ),
  150. ),
  151. );
  152. },
  153. );
  154. }
  155. }
  156. class AddToAlbumTitleRow extends StatelessWidget {
  157. const AddToAlbumTitleRow({
  158. super.key,
  159. required this.onCreateNewAlbum,
  160. });
  161. final VoidCallback onCreateNewAlbum;
  162. @override
  163. Widget build(BuildContext context) {
  164. return Padding(
  165. padding: const EdgeInsets.symmetric(horizontal: 16),
  166. child: Row(
  167. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  168. children: [
  169. const Text(
  170. "control_bottom_app_bar_add_to_album",
  171. style: TextStyle(
  172. fontSize: 14,
  173. fontWeight: FontWeight.bold,
  174. ),
  175. ).tr(),
  176. TextButton(
  177. onPressed: onCreateNewAlbum,
  178. child: Text(
  179. "control_bottom_app_bar_create_new_album",
  180. style: TextStyle(
  181. color: Theme.of(context).primaryColor,
  182. fontWeight: FontWeight.bold,
  183. fontSize: 14,
  184. ),
  185. ).tr(),
  186. ),
  187. ],
  188. ),
  189. );
  190. }
  191. }
  192. class CustomDraggingHandle extends StatelessWidget {
  193. const CustomDraggingHandle({super.key});
  194. @override
  195. Widget build(BuildContext context) {
  196. return Container(
  197. height: 5,
  198. width: 30,
  199. decoration: BoxDecoration(
  200. color: Colors.grey[500],
  201. borderRadius: BorderRadius.circular(16),
  202. ),
  203. );
  204. }
  205. }
  206. class ControlBoxButton extends StatelessWidget {
  207. const ControlBoxButton({
  208. Key? key,
  209. required this.label,
  210. required this.iconData,
  211. required this.onPressed,
  212. }) : super(key: key);
  213. final String label;
  214. final IconData iconData;
  215. final Function onPressed;
  216. @override
  217. Widget build(BuildContext context) {
  218. return MaterialButton(
  219. padding: const EdgeInsets.all(10),
  220. shape: const CircleBorder(),
  221. onPressed: () => onPressed(),
  222. child: Column(
  223. mainAxisAlignment: MainAxisAlignment.start,
  224. crossAxisAlignment: CrossAxisAlignment.center,
  225. children: [
  226. Icon(iconData, size: 24),
  227. const SizedBox(height: 6),
  228. Text(
  229. label,
  230. style: const TextStyle(fontSize: 12.0),
  231. ),
  232. ],
  233. ),
  234. );
  235. }
  236. }