path_storage_viewer.dart 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. import 'dart:io';
  2. import 'package:flutter/foundation.dart';
  3. import 'package:flutter/material.dart';
  4. import 'package:flutter/services.dart';
  5. import 'package:logging/logging.dart';
  6. import 'package:photos/theme/ente_theme.dart';
  7. import 'package:photos/ui/components/captioned_text_widget.dart';
  8. import 'package:photos/ui/components/menu_item_widget/menu_item_widget.dart';
  9. import 'package:photos/utils/data_util.dart';
  10. import 'package:photos/utils/directory_content.dart';
  11. class PathStorageItem {
  12. final String path;
  13. final String title;
  14. final bool allowCacheClear;
  15. PathStorageItem.name(
  16. this.path,
  17. this.title, {
  18. this.allowCacheClear = false,
  19. });
  20. }
  21. class PathStorageViewer extends StatefulWidget {
  22. final PathStorageItem item;
  23. final bool removeTopRadius;
  24. final bool removeBottomRadius;
  25. final bool enableDoubleTapClear;
  26. const PathStorageViewer(
  27. this.item, {
  28. this.removeTopRadius = false,
  29. this.removeBottomRadius = false,
  30. this.enableDoubleTapClear = false,
  31. Key? key,
  32. }) : super(key: key);
  33. @override
  34. State<PathStorageViewer> createState() => _PathStorageViewerState();
  35. }
  36. class _PathStorageViewerState extends State<PathStorageViewer> {
  37. final Logger _logger = Logger((_PathStorageViewerState).toString());
  38. @override
  39. void initState() {
  40. super.initState();
  41. }
  42. void _safeRefresh() async {
  43. if (mounted) {
  44. setState(() => {});
  45. }
  46. }
  47. @override
  48. Widget build(BuildContext context) {
  49. return FutureBuilder<DirectoryStat>(
  50. future: getDirectorySize(Directory(widget.item.path)),
  51. builder: (context, snapshot) {
  52. if (snapshot.hasData) {
  53. return _buildMenuItemWidget(snapshot.data, null);
  54. } else if (snapshot.hasError) {
  55. _logger.severe(
  56. "Failed to get state for ${widget.item.title}",
  57. snapshot.error,
  58. );
  59. return _buildMenuItemWidget(null, snapshot.error);
  60. } else {
  61. return _buildMenuItemWidget(null, null);
  62. }
  63. },
  64. );
  65. }
  66. Widget _buildMenuItemWidget(DirectoryStat? stat, Object? err) {
  67. return MenuItemWidget(
  68. key: UniqueKey(),
  69. alignCaptionedTextToLeft: true,
  70. captionedTextWidget: CaptionedTextWidget(
  71. title: widget.item.title,
  72. subTitle: stat != null ? '${stat.fileCount}' : null,
  73. subTitleColor: getEnteColorScheme(context).textFaint,
  74. ),
  75. trailingWidget: stat != null
  76. ? Text(
  77. formatBytes(stat.size),
  78. style: getEnteTextTheme(context)
  79. .small
  80. .copyWith(color: getEnteColorScheme(context).textFaint),
  81. )
  82. : SizedBox.fromSize(
  83. size: const Size.square(14),
  84. child: CircularProgressIndicator(
  85. strokeWidth: 2,
  86. color: getEnteColorScheme(context).strokeMuted,
  87. ),
  88. ),
  89. trailingIcon: err != null ? Icons.error_outline_outlined : null,
  90. trailingIconIsMuted: err != null,
  91. singleBorderRadius: 8,
  92. menuItemColor: getEnteColorScheme(context).fillFaint,
  93. isBottomBorderRadiusRemoved: widget.removeBottomRadius,
  94. isTopBorderRadiusRemoved: widget.removeTopRadius,
  95. showOnlyLoadingState: true,
  96. onTap: () async {
  97. if (kDebugMode) {
  98. await Clipboard.setData(ClipboardData(text: widget.item.path));
  99. debugPrint(widget.item.path);
  100. }
  101. },
  102. onDoubleTap: () async {
  103. if (widget.item.allowCacheClear && widget.enableDoubleTapClear) {
  104. await deleteDirectoryContents(widget.item.path);
  105. _safeRefresh();
  106. }
  107. },
  108. );
  109. }
  110. }