file_icons_widget.dart 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. import 'package:flutter/material.dart';
  2. import 'package:photos/ente_theme_data.dart';
  3. import 'package:photos/models/collection.dart';
  4. import 'package:photos/models/trash_file.dart';
  5. import 'package:photos/theme/colors.dart';
  6. import 'package:photos/ui/sharing/user_avator_widget.dart';
  7. import 'package:photos/utils/date_time_util.dart';
  8. class ThumbnailPlaceHolder extends StatelessWidget {
  9. const ThumbnailPlaceHolder({Key? key}) : super(key: key);
  10. @override
  11. Widget build(BuildContext context) {
  12. return Container(
  13. alignment: Alignment.center,
  14. color: Theme.of(context).colorScheme.galleryThumbBackgroundColor,
  15. );
  16. }
  17. }
  18. class UnSyncedIcon extends StatelessWidget {
  19. const UnSyncedIcon({Key? key}) : super(key: key);
  20. @override
  21. Widget build(BuildContext context) {
  22. return const _BottomLeftOverlayIcon(Icons.cloud_off_outlined);
  23. }
  24. }
  25. class FavoriteOverlayIcon extends StatelessWidget {
  26. const FavoriteOverlayIcon({Key? key}) : super(key: key);
  27. @override
  28. Widget build(BuildContext context) {
  29. return const _BottomLeftOverlayIcon(
  30. Icons.favorite_rounded,
  31. baseSize: 22,
  32. );
  33. }
  34. }
  35. class ArchiveOverlayIcon extends StatelessWidget {
  36. const ArchiveOverlayIcon({Key? key}) : super(key: key);
  37. @override
  38. Widget build(BuildContext context) {
  39. return const _BottomLeftOverlayIcon(
  40. Icons.archive_outlined,
  41. color: fixedStrokeMutedWhite,
  42. );
  43. }
  44. }
  45. class LivePhotoOverlayIcon extends StatelessWidget {
  46. const LivePhotoOverlayIcon({Key? key}) : super(key: key);
  47. @override
  48. Widget build(BuildContext context) {
  49. return const _BottomRightOverlayIcon(
  50. Icons.album_outlined,
  51. baseSize: 18,
  52. );
  53. }
  54. }
  55. class VideoOverlayIcon extends StatelessWidget {
  56. const VideoOverlayIcon({Key? key}) : super(key: key);
  57. @override
  58. Widget build(BuildContext context) {
  59. return const SizedBox(
  60. height: 64,
  61. child: Icon(
  62. Icons.play_circle_outline,
  63. size: 40,
  64. color: Colors.white70,
  65. ),
  66. );
  67. }
  68. }
  69. class OwnerAvatarOverlayIcon extends StatelessWidget {
  70. final User user;
  71. const OwnerAvatarOverlayIcon(this.user, {Key? key}) : super(key: key);
  72. @override
  73. Widget build(BuildContext context) {
  74. return Align(
  75. alignment: Alignment.topRight,
  76. child: Padding(
  77. padding: const EdgeInsets.only(right: 4, top: 4),
  78. child: UserAvatarWidget(
  79. user,
  80. type: AvatarType.tiny,
  81. thumbnailView: true,
  82. ),
  83. ),
  84. );
  85. }
  86. }
  87. class TrashedFileOverlayText extends StatelessWidget {
  88. final TrashFile file;
  89. const TrashedFileOverlayText(this.file, {Key? key}) : super(key: key);
  90. @override
  91. Widget build(BuildContext context) {
  92. return Container(
  93. decoration: BoxDecoration(
  94. gradient: LinearGradient(
  95. begin: Alignment.bottomCenter,
  96. end: Alignment.topCenter,
  97. colors: [Colors.black.withOpacity(0.33), Colors.transparent],
  98. ),
  99. ),
  100. alignment: Alignment.bottomCenter,
  101. padding: const EdgeInsets.only(bottom: 5),
  102. child: Text(
  103. daysLeft(file.deleteBy),
  104. style: Theme.of(context)
  105. .textTheme
  106. .subtitle2!
  107. .copyWith(color: Colors.white), //same for both themes
  108. ),
  109. );
  110. }
  111. }
  112. // Base variations
  113. /// Icon overlay in the bottom left.
  114. ///
  115. /// This usually indicates ente specific state of a file, e.g. if it is
  116. /// favorited/archived.
  117. class _BottomLeftOverlayIcon extends StatelessWidget {
  118. final IconData icon;
  119. /// Overriddable color. Default is a fixed white.
  120. final Color color;
  121. /// Overriddable default size. This is just the initial hint, the actual size
  122. /// is dynamic based on the widget's width (so that we show smaller icons in
  123. /// smaller thumbnails).
  124. final double baseSize;
  125. const _BottomLeftOverlayIcon(
  126. this.icon, {
  127. Key? key,
  128. this.baseSize = 24,
  129. this.color = Colors.white, // fixed
  130. }) : super(key: key);
  131. @override
  132. Widget build(BuildContext context) {
  133. return LayoutBuilder(
  134. builder: (context, constraints) {
  135. double inset = 4;
  136. double size = baseSize;
  137. if (constraints.hasBoundedWidth) {
  138. final w = constraints.maxWidth;
  139. if (w > 120) {
  140. size = 24;
  141. } else if (w < 75) {
  142. inset = 3;
  143. size = 16;
  144. }
  145. }
  146. return Container(
  147. decoration: const BoxDecoration(
  148. gradient: LinearGradient(
  149. begin: Alignment.bottomLeft,
  150. end: Alignment.center,
  151. colors: [
  152. Color.fromRGBO(0, 0, 0, 0.14),
  153. Color.fromRGBO(0, 0, 0, 0.05),
  154. Color.fromRGBO(0, 0, 0, 0.0),
  155. ],
  156. stops: [0, 0.6, 1],
  157. ),
  158. ),
  159. child: Align(
  160. alignment: Alignment.bottomLeft,
  161. child: Padding(
  162. padding: EdgeInsets.only(left: inset, bottom: inset),
  163. child: Icon(
  164. icon,
  165. size: size,
  166. color: color,
  167. ),
  168. ),
  169. ),
  170. );
  171. },
  172. );
  173. }
  174. }
  175. /// Icon overlay in the bottom right.
  176. ///
  177. /// This usually indicates information about the file itself, e.g. whether it is
  178. /// a live photo, or the duration of the video.
  179. class _BottomRightOverlayIcon extends StatelessWidget {
  180. final IconData icon;
  181. /// Overriddable color. Default is a fixed white.
  182. final Color color;
  183. /// Overriddable default size. This is just the initial hint, the actual size
  184. /// is dynamic based on the widget's width (so that we show smaller icons in
  185. /// smaller thumbnails).
  186. final double baseSize;
  187. const _BottomRightOverlayIcon(
  188. this.icon, {
  189. Key? key,
  190. this.baseSize = 24,
  191. this.color = Colors.white, // fixed
  192. }) : super(key: key);
  193. @override
  194. Widget build(BuildContext context) {
  195. return LayoutBuilder(
  196. builder: (context, constraints) {
  197. double inset = 4;
  198. double size = baseSize;
  199. if (constraints.hasBoundedWidth) {
  200. final w = constraints.maxWidth;
  201. if (w > 120) {
  202. size = 24;
  203. } else if (w < 75) {
  204. inset = 3;
  205. size = 16;
  206. }
  207. }
  208. return Container(
  209. decoration: const BoxDecoration(
  210. gradient: LinearGradient(
  211. begin: Alignment.bottomRight,
  212. end: Alignment.center,
  213. colors: [
  214. Color.fromRGBO(0, 0, 0, 0.14),
  215. Color.fromRGBO(0, 0, 0, 0.05),
  216. Color.fromRGBO(0, 0, 0, 0.0),
  217. ],
  218. stops: [0, 0.6, 1],
  219. ),
  220. ),
  221. child: Align(
  222. alignment: Alignment.bottomRight,
  223. child: Padding(
  224. padding: EdgeInsets.only(bottom: inset, right: inset),
  225. child: Icon(
  226. icon,
  227. size: size,
  228. color: color,
  229. ),
  230. ),
  231. ),
  232. );
  233. },
  234. );
  235. }
  236. }