selection_thumbnail_image.dart 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. import 'package:cached_network_image/cached_network_image.dart';
  2. import 'package:flutter/material.dart';
  3. import 'package:flutter_hooks/flutter_hooks.dart';
  4. import 'package:hive_flutter/hive_flutter.dart';
  5. import 'package:hooks_riverpod/hooks_riverpod.dart';
  6. import 'package:immich_mobile/constants/hive_box.dart';
  7. import 'package:immich_mobile/modules/sharing/providers/asset_selection.provider.dart';
  8. import 'package:openapi/api.dart';
  9. class SelectionThumbnailImage extends HookConsumerWidget {
  10. final AssetResponseDto asset;
  11. const SelectionThumbnailImage({Key? key, required this.asset})
  12. : super(key: key);
  13. @override
  14. Widget build(BuildContext context, WidgetRef ref) {
  15. final cacheKey = useState(1);
  16. var box = Hive.box(userInfoBox);
  17. var thumbnailRequestUrl =
  18. '${box.get(serverEndpointKey)}/asset/thumbnail/${asset.id}';
  19. var selectedAsset =
  20. ref.watch(assetSelectionProvider).selectedNewAssetsForAlbum;
  21. var newAssetsForAlbum =
  22. ref.watch(assetSelectionProvider).selectedAdditionalAssetsForAlbum;
  23. var isAlbumExist = ref.watch(assetSelectionProvider).isAlbumExist;
  24. Widget _buildSelectionIcon(AssetResponseDto asset) {
  25. var isSelected = selectedAsset.map((item) => item.id).contains(asset.id);
  26. var isNewlySelected =
  27. newAssetsForAlbum.map((item) => item.id).contains(asset.id);
  28. if (isSelected && !isAlbumExist) {
  29. return Icon(
  30. Icons.check_circle,
  31. color: Theme.of(context).primaryColor,
  32. );
  33. } else if (isSelected && isAlbumExist) {
  34. return const Icon(
  35. Icons.check_circle,
  36. color: Color.fromARGB(255, 233, 233, 233),
  37. );
  38. } else if (isNewlySelected && isAlbumExist) {
  39. return Icon(
  40. Icons.check_circle,
  41. color: Theme.of(context).primaryColor,
  42. );
  43. } else {
  44. return const Icon(
  45. Icons.circle_outlined,
  46. color: Colors.white,
  47. );
  48. }
  49. }
  50. BoxBorder drawBorderColor() {
  51. var isSelected = selectedAsset.map((item) => item.id).contains(asset.id);
  52. var isNewlySelected =
  53. newAssetsForAlbum.map((item) => item.id).contains(asset.id);
  54. if (isSelected && !isAlbumExist) {
  55. return Border.all(
  56. color: Theme.of(context).primaryColorLight,
  57. width: 10,
  58. );
  59. } else if (isSelected && isAlbumExist) {
  60. return Border.all(
  61. color: const Color.fromARGB(255, 190, 190, 190),
  62. width: 10,
  63. );
  64. } else if (isNewlySelected && isAlbumExist) {
  65. return Border.all(
  66. color: Theme.of(context).primaryColorLight,
  67. width: 10,
  68. );
  69. }
  70. return const Border();
  71. }
  72. return GestureDetector(
  73. onTap: () {
  74. var isSelected =
  75. selectedAsset.map((item) => item.id).contains(asset.id);
  76. var isNewlySelected =
  77. newAssetsForAlbum.map((item) => item.id).contains(asset.id);
  78. if (isAlbumExist) {
  79. // Operation for existing album
  80. if (!isSelected) {
  81. if (isNewlySelected) {
  82. ref
  83. .watch(assetSelectionProvider.notifier)
  84. .removeSelectedAdditionalAssets([asset]);
  85. } else {
  86. ref
  87. .watch(assetSelectionProvider.notifier)
  88. .addAdditionalAssets([asset]);
  89. }
  90. }
  91. } else {
  92. // Operation for new album
  93. if (isSelected) {
  94. ref
  95. .watch(assetSelectionProvider.notifier)
  96. .removeSelectedNewAssets([asset]);
  97. } else {
  98. ref.watch(assetSelectionProvider.notifier).addNewAssets([asset]);
  99. }
  100. }
  101. },
  102. child: Stack(
  103. children: [
  104. Container(
  105. decoration: BoxDecoration(border: drawBorderColor()),
  106. child: CachedNetworkImage(
  107. cacheKey: "${asset.id}-${cacheKey.value}",
  108. width: 150,
  109. height: 150,
  110. memCacheHeight: asset.type == AssetTypeEnum.IMAGE ? 150 : 150,
  111. fit: BoxFit.cover,
  112. imageUrl: thumbnailRequestUrl,
  113. httpHeaders: {
  114. "Authorization": "Bearer ${box.get(accessTokenKey)}"
  115. },
  116. fadeInDuration: const Duration(milliseconds: 250),
  117. progressIndicatorBuilder: (context, url, downloadProgress) =>
  118. Transform.scale(
  119. scale: 0.2,
  120. child:
  121. CircularProgressIndicator(value: downloadProgress.progress),
  122. ),
  123. errorWidget: (context, url, error) {
  124. return Icon(
  125. Icons.image_not_supported_outlined,
  126. color: Theme.of(context).primaryColor,
  127. );
  128. },
  129. ),
  130. ),
  131. Padding(
  132. padding: const EdgeInsets.all(3.0),
  133. child: Align(
  134. alignment: Alignment.topLeft,
  135. child: _buildSelectionIcon(asset),
  136. ),
  137. ),
  138. if (asset.type != AssetTypeEnum.IMAGE)
  139. Positioned(
  140. bottom: 5,
  141. right: 5,
  142. child: Row(
  143. children: [
  144. Text(
  145. asset.duration.substring(0, 7),
  146. style: const TextStyle(
  147. color: Colors.white,
  148. fontSize: 10,
  149. ),
  150. ),
  151. const Icon(
  152. Icons.play_circle_outline_rounded,
  153. color: Colors.white,
  154. ),
  155. ],
  156. ),
  157. ),
  158. ],
  159. ),
  160. );
  161. }
  162. }