thumbnail_image.dart 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. import 'package:auto_route/auto_route.dart';
  2. import 'package:cached_network_image/cached_network_image.dart';
  3. import 'package:flutter/material.dart';
  4. import 'package:flutter/services.dart';
  5. import 'package:flutter_hooks/flutter_hooks.dart';
  6. import 'package:hive_flutter/hive_flutter.dart';
  7. import 'package:hooks_riverpod/hooks_riverpod.dart';
  8. import 'package:immich_mobile/constants/hive_box.dart';
  9. import 'package:immich_mobile/modules/home/providers/home_page_state.provider.dart';
  10. import 'package:immich_mobile/shared/models/immich_asset.model.dart';
  11. import 'package:immich_mobile/routing/router.dart';
  12. class ThumbnailImage extends HookConsumerWidget {
  13. final ImmichAsset asset;
  14. const ThumbnailImage({Key? key, required this.asset}) : super(key: key);
  15. @override
  16. Widget build(BuildContext context, WidgetRef ref) {
  17. final cacheKey = useState(1);
  18. var box = Hive.box(userInfoBox);
  19. var thumbnailRequestUrl =
  20. '${box.get(serverEndpointKey)}/asset/file?aid=${asset.deviceAssetId}&did=${asset.deviceId}&isThumb=true';
  21. var selectedAsset = ref.watch(homePageStateProvider).selectedItems;
  22. var isMultiSelectEnable = ref.watch(homePageStateProvider).isMultiSelectEnable;
  23. Widget _buildSelectionIcon(ImmichAsset asset) {
  24. if (selectedAsset.contains(asset)) {
  25. return Icon(
  26. Icons.check_circle,
  27. color: Theme.of(context).primaryColor,
  28. );
  29. } else {
  30. return const Icon(
  31. Icons.circle_outlined,
  32. color: Colors.white,
  33. );
  34. }
  35. }
  36. return GestureDetector(
  37. onTap: () {
  38. if (isMultiSelectEnable && selectedAsset.contains(asset) && selectedAsset.length == 1) {
  39. ref.watch(homePageStateProvider.notifier).disableMultiSelect();
  40. } else if (isMultiSelectEnable && selectedAsset.contains(asset) && selectedAsset.length > 1) {
  41. ref.watch(homePageStateProvider.notifier).removeSingleSelectedItem(asset);
  42. } else if (isMultiSelectEnable && !selectedAsset.contains(asset)) {
  43. ref.watch(homePageStateProvider.notifier).addSingleSelectedItem(asset);
  44. } else {
  45. if (asset.type == 'IMAGE') {
  46. AutoRouter.of(context).push(
  47. ImageViewerRoute(
  48. imageUrl:
  49. '${box.get(serverEndpointKey)}/asset/file?aid=${asset.deviceAssetId}&did=${asset.deviceId}&isThumb=false',
  50. heroTag: asset.id,
  51. thumbnailUrl: thumbnailRequestUrl,
  52. asset: asset,
  53. ),
  54. );
  55. } else {
  56. debugPrint("Navigate to video player");
  57. AutoRouter.of(context).push(
  58. VideoViewerRoute(
  59. videoUrl: '${box.get(serverEndpointKey)}/asset/file?aid=${asset.deviceAssetId}&did=${asset.deviceId}',
  60. ),
  61. );
  62. }
  63. }
  64. },
  65. onLongPress: () {
  66. // Enable multi selecte function
  67. ref.watch(homePageStateProvider.notifier).enableMultiSelect({asset});
  68. HapticFeedback.heavyImpact();
  69. },
  70. child: Hero(
  71. tag: asset.id,
  72. child: Stack(
  73. children: [
  74. Container(
  75. decoration: BoxDecoration(
  76. border: isMultiSelectEnable && selectedAsset.contains(asset)
  77. ? Border.all(color: Theme.of(context).primaryColorLight, width: 10)
  78. : const Border(),
  79. ),
  80. child: CachedNetworkImage(
  81. cacheKey: "${asset.id}-${cacheKey.value}",
  82. width: 300,
  83. height: 300,
  84. memCacheHeight: asset.type == 'IMAGE' ? 250 : 400,
  85. fit: BoxFit.cover,
  86. imageUrl: thumbnailRequestUrl,
  87. httpHeaders: {"Authorization": "Bearer ${box.get(accessTokenKey)}"},
  88. fadeInDuration: const Duration(milliseconds: 250),
  89. progressIndicatorBuilder: (context, url, downloadProgress) => Transform.scale(
  90. scale: 0.2,
  91. child: CircularProgressIndicator(value: downloadProgress.progress),
  92. ),
  93. errorWidget: (context, url, error) {
  94. debugPrint("Error Loading Thumbnail Widget $error");
  95. cacheKey.value += 1;
  96. return const Icon(Icons.error);
  97. },
  98. ),
  99. ),
  100. Container(
  101. child: isMultiSelectEnable
  102. ? Padding(
  103. padding: const EdgeInsets.all(3.0),
  104. child: Align(
  105. alignment: Alignment.topLeft,
  106. child: _buildSelectionIcon(asset),
  107. ),
  108. )
  109. : Container(),
  110. ),
  111. ],
  112. ),
  113. ),
  114. );
  115. }
  116. }