Просмотр исходного кода

Use a single cache for thumbnails

Vishnu Mohandas 5 лет назад
Родитель
Сommit
873f1b631d
3 измененных файлов с 66 добавлено и 98 удалено
  1. 30 73
      lib/ui/thumbnail_widget.dart
  2. 6 25
      lib/ui/zoomable_image.dart
  3. 30 0
      lib/utils/file_util.dart

+ 30 - 73
lib/ui/thumbnail_widget.dart

@@ -1,19 +1,10 @@
-import 'package:cached_network_image/cached_network_image.dart';
-import 'package:dio/dio.dart';
 import 'package:flutter/material.dart';
-import 'package:flutter_cache_manager/flutter_cache_manager.dart';
-import 'package:photos/core/cache/image_cache.dart';
-import 'dart:io' as io;
 import 'package:photos/core/cache/thumbnail_cache.dart';
-import 'package:photos/core/cache/thumbnail_cache_manager.dart';
-import 'package:photos/core/configuration.dart';
 import 'package:photos/file_repository.dart';
 import 'package:photos/models/file.dart';
 import 'package:logging/logging.dart';
 import 'package:photos/core/constants.dart';
 import 'package:photos/models/file_type.dart';
-import 'package:photos/ui/loading_widget.dart';
-import 'package:photos/utils/crypto_util.dart';
 import 'package:photos/utils/file_util.dart';
 
 class ThumbnailWidget extends StatefulWidget {
@@ -36,23 +27,25 @@ class _ThumbnailWidgetState extends State<ThumbnailWidget> {
   );
 
   bool _hasLoadedThumbnail = false;
+  bool _isLoadingThumbnail = false;
   bool _encounteredErrorLoadingThumbnail = false;
   ImageProvider _imageProvider;
 
   @override
   Widget build(BuildContext context) {
-    var image;
     if (widget.file.localID == null) {
-      image = _getNetworkImage();
+      _loadNetworkImage();
     } else {
       _loadLocalImage(context);
-      if (_imageProvider != null) {
-        image = Image(
-          image: _imageProvider,
-          fit: widget.fit,
-        );
-      }
     }
+    var image;
+    if (_imageProvider != null) {
+      image = Image(
+        image: _imageProvider,
+        fit: widget.fit,
+      );
+    }
+
     var content;
     if (image != null) {
       if (widget.file.fileType == FileType.video) {
@@ -81,7 +74,10 @@ class _ThumbnailWidgetState extends State<ThumbnailWidget> {
   }
 
   void _loadLocalImage(BuildContext context) {
-    if (!_hasLoadedThumbnail && !_encounteredErrorLoadingThumbnail) {
+    if (!_hasLoadedThumbnail &&
+        !_encounteredErrorLoadingThumbnail &&
+        !_isLoadingThumbnail) {
+      _isLoadingThumbnail = true;
       final cachedSmallThumbnail =
           ThumbnailLruCache.get(widget.file, THUMBNAIL_SMALL_SIZE);
       if (cachedSmallThumbnail != null) {
@@ -118,62 +114,22 @@ class _ThumbnailWidgetState extends State<ThumbnailWidget> {
     }
   }
 
-  Widget _getNetworkImage() {
-    if (!widget.file.isEncrypted) {
-      return CachedNetworkImage(
-        imageUrl: widget.file.getThumbnailUrl(),
-        placeholder: (context, url) => loadWidget,
-        errorWidget: (context, url, error) => Icon(Icons.error),
-        fit: BoxFit.cover,
-        cacheManager: ThumbnailCacheManager(),
-      );
-    } else {
-      if (ThumbnailFileLruCache.get(widget.file) != null) {
-        return Image.file(
-          ThumbnailFileLruCache.get(widget.file),
-          fit: widget.fit,
-        );
-      }
-      final thumbnailPath = Configuration.instance.getThumbnailsDirectory() +
-          widget.file.generatedID.toString() +
-          ".jpg";
-      final thumbnailFile = io.File(thumbnailPath);
-      if (thumbnailFile.existsSync()) {
-        ThumbnailFileLruCache.put(widget.file, thumbnailFile);
-        return Image.file(
-          thumbnailFile,
-          fit: widget.fit,
-        );
-      } else {
-        final temporaryPath = Configuration.instance.getTempDirectory() +
-            widget.file.generatedID.toString() +
-            "_thumbnail.aes";
-        final decryptedFileFuture = Dio()
-            .download(widget.file.getThumbnailUrl(), temporaryPath)
-            .then((_) async {
-          await CryptoUtil.decryptFileToFile(
-              temporaryPath, thumbnailPath, Configuration.instance.getKey());
-          io.File(temporaryPath).deleteSync();
-          return io.File(thumbnailPath);
+  void _loadNetworkImage() {
+    if (!_hasLoadedThumbnail &&
+        !_encounteredErrorLoadingThumbnail &&
+        !_isLoadingThumbnail) {
+      _isLoadingThumbnail = true;
+      getThumbnailFromServer(widget.file).then((file) {
+        final imageProvider = Image.file(file).image;
+        precacheImage(imageProvider, context).then((value) {
+          if (mounted) {
+            setState(() {
+              _imageProvider = imageProvider;
+              _hasLoadedThumbnail = true;
+            });
+          }
         });
-        return FutureBuilder<io.File>(
-          future: decryptedFileFuture,
-          builder: (context, snapshot) {
-            if (snapshot.hasData) {
-              ThumbnailFileLruCache.put(widget.file, snapshot.data);
-              return Image.file(
-                snapshot.data,
-                fit: widget.fit,
-              );
-            } else if (snapshot.hasError) {
-              _logger.warning(snapshot.error);
-              return Text(snapshot.error.toString());
-            } else {
-              return loadingWidget;
-            }
-          },
-        );
-      }
+      });
     }
   }
 
@@ -183,6 +139,7 @@ class _ThumbnailWidgetState extends State<ThumbnailWidget> {
     if (widget.file.generatedID != oldWidget.file.generatedID) {
       setState(() {
         _hasLoadedThumbnail = false;
+        _isLoadingThumbnail = false;
         _imageProvider = null;
       });
     }

+ 6 - 25
lib/ui/zoomable_image.dart

@@ -78,10 +78,12 @@ class _ZoomableImageState extends State<ZoomableImage>
   }
 
   void _loadNetworkImage() {
-    if (!_photo.isEncrypted) {
-      _loadUnencryptedThumbnail();
-    } else {
-      _loadEncryptedThumbnail();
+    if (!_loadedSmallThumbnail && !_loadedFinalImage) {
+      _imageProvider = CachedNetworkImageProvider(
+        _photo.getThumbnailUrl(),
+        cacheManager: ThumbnailCacheManager(),
+      );
+      _loadedSmallThumbnail = true;
     }
     if (!_loadedFinalImage) {
       getFileFromServer(_photo).then((file) {
@@ -95,27 +97,6 @@ class _ZoomableImageState extends State<ZoomableImage>
     }
   }
 
-  void _loadUnencryptedThumbnail() {
-    if (!_loadedSmallThumbnail && !_loadedFinalImage) {
-      _imageProvider = CachedNetworkImageProvider(
-        _photo.getThumbnailUrl(),
-        cacheManager: ThumbnailCacheManager(),
-      );
-      _loadedSmallThumbnail = true;
-    }
-  }
-
-  void _loadEncryptedThumbnail() {
-    if (!_loadedSmallThumbnail && !_loadedFinalImage) {
-      if (ThumbnailFileLruCache.get(_photo) != null) {
-        _imageProvider = Image.file(
-          ThumbnailFileLruCache.get(_photo),
-        ).image;
-        _loadedSmallThumbnail = true;
-      }
-    }
-  }
-
   void _loadLocalImage(BuildContext context) {
     if (!_loadedSmallThumbnail &&
         !_loadedLargeThumbnail &&

+ 30 - 0
lib/utils/file_util.dart

@@ -8,6 +8,7 @@ import 'package:flutter_image_compress/flutter_image_compress.dart';
 import 'package:photo_manager/photo_manager.dart';
 import 'package:photos/core/cache/image_cache.dart';
 import 'package:photos/core/cache/thumbnail_cache.dart';
+import 'package:photos/core/cache/thumbnail_cache_manager.dart';
 import 'package:photos/core/cache/video_cache_manager.dart';
 import 'package:photos/core/configuration.dart';
 import 'package:photos/core/constants.dart';
@@ -98,6 +99,22 @@ Future<io.File> getFileFromServer(File file) async {
   }
 }
 
+Future<io.File> getThumbnailFromServer(File file) async {
+  if (!file.isEncrypted) {
+    return ThumbnailCacheManager().getSingleFile(file.getThumbnailUrl());
+  } else {
+    return ThumbnailCacheManager()
+        .getFileFromCache(file.getThumbnailUrl())
+        .then((info) {
+      if (info == null) {
+        return _downloadAndDecryptThumbnail(file);
+      } else {
+        return info.file;
+      }
+    });
+  }
+}
+
 Future<io.File> _downloadAndDecrypt(
     File file, BaseCacheManager cacheManager) async {
   final temporaryPath = Configuration.instance.getTempDirectory() +
@@ -110,3 +127,16 @@ Future<io.File> _downloadAndDecrypt(
     return cacheManager.putFile(file.getDownloadUrl(), data);
   });
 }
+
+Future<io.File> _downloadAndDecryptThumbnail(File file) async {
+  final temporaryPath = Configuration.instance.getTempDirectory() +
+      file.generatedID.toString() +
+      "_thumbnail.aes";
+  Dio dio = Dio();
+  return dio.download(file.getThumbnailUrl(), temporaryPath).then((_) async {
+    final data = await CryptoUtil.decryptFileToData(
+        temporaryPath, Configuration.instance.getKey());
+    io.File(temporaryPath).deleteSync();
+    return ThumbnailCacheManager().putFile(file.getThumbnailUrl(), data);
+  });
+}