Add support for uploading & reading image from app cache
This commit is contained in:
parent
9e2c555dbc
commit
9adf41fd2e
|
@ -82,7 +82,7 @@ class File {
|
|||
|
||||
Map<String, dynamic> getMetadata() {
|
||||
final metadata = Map<String, dynamic>();
|
||||
metadata["localID"] = localID;
|
||||
metadata["localID"] = isCachedInAppSandbox() ? null : localID;
|
||||
metadata["title"] = title;
|
||||
metadata["deviceFolder"] = deviceFolder;
|
||||
metadata["creationTime"] = creationTime;
|
||||
|
@ -129,10 +129,15 @@ class File {
|
|||
}
|
||||
}
|
||||
|
||||
// returns true if the file isn't available in the user's gallery
|
||||
bool isRemoteFile() {
|
||||
return localID == null && uploadedFileID != null;
|
||||
}
|
||||
|
||||
bool isCachedInAppSandbox() {
|
||||
return localID != null && localID.startsWith("ente-upload-cache");
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return '''File(generatedId: $generatedID, uploadedFileId: $uploadedFileID,
|
||||
|
|
|
@ -24,8 +24,11 @@ class MediaUploadData {
|
|||
}
|
||||
|
||||
Future<MediaUploadData> getUploadDataFromEnteFile(ente.File file) async {
|
||||
// todo: add local to get data from either Asset/photoManager or app cache
|
||||
return await _getMediaUploadDataFromAssetFile(file);
|
||||
if (file.isCachedInAppSandbox()) {
|
||||
return await _getMediaUploadDataFromAppCache(file);
|
||||
} else {
|
||||
return await _getMediaUploadDataFromAssetFile(file);
|
||||
}
|
||||
}
|
||||
|
||||
Future<MediaUploadData> _getMediaUploadDataFromAssetFile(ente.File file) async {
|
||||
|
@ -93,3 +96,32 @@ Future<void> _decorateEnteFileData(ente.File file, AssetEntity asset) async {
|
|||
file.title = await asset.titleAsync;
|
||||
}
|
||||
}
|
||||
|
||||
Future<MediaUploadData> _getMediaUploadDataFromAppCache(ente.File file) async {
|
||||
io.File sourceFile;
|
||||
Uint8List thumbnailData;
|
||||
bool isDeleted = false;
|
||||
var localPath = file.localID.replaceAll(RegExp(r'ente-upload-cache:'), '');
|
||||
sourceFile = io.File(localPath);
|
||||
if (!sourceFile.existsSync()) {
|
||||
_logger.warning("File doesn't exist in app sandbox");
|
||||
throw InvalidFileError();
|
||||
}
|
||||
thumbnailData = await getThumbnailFromInAppCacheFile(file);
|
||||
return MediaUploadData(sourceFile, thumbnailData, isDeleted);
|
||||
}
|
||||
|
||||
Future<Uint8List> getThumbnailFromInAppCacheFile(ente.File file) async {
|
||||
var localPath = file.localID.replaceAll(RegExp(r'ente-upload-cache:'), '');
|
||||
var thumbnailData = io.File(localPath).readAsBytesSync();
|
||||
int compressionAttempts = 0;
|
||||
while (thumbnailData.length > THUMBNAIL_DATA_LIMIT &&
|
||||
compressionAttempts < kMaximumThumbnailCompressionAttempts) {
|
||||
_logger.info("Thumbnail size " + thumbnailData.length.toString());
|
||||
thumbnailData = await compressThumbnail(thumbnailData);
|
||||
_logger
|
||||
.info("Compressed thumbnail size " + thumbnailData.length.toString());
|
||||
compressionAttempts++;
|
||||
}
|
||||
return thumbnailData;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import 'package:photos/services/collections_service.dart';
|
|||
import 'package:photos/utils/thumbnail_util.dart';
|
||||
|
||||
import 'crypto_util.dart';
|
||||
import 'file_uploader_util.dart';
|
||||
|
||||
final _logger = Logger("FileUtil");
|
||||
|
||||
|
@ -36,7 +37,7 @@ Future<io.File> getFile(ente.File file) async {
|
|||
} else {
|
||||
final cachedFile = FileLruCache.get(file);
|
||||
if (cachedFile == null) {
|
||||
final diskFile = await (await file.getAsset()).file;
|
||||
final diskFile = await _getLocalDiskFile(file);
|
||||
FileLruCache.put(file, diskFile);
|
||||
return diskFile;
|
||||
}
|
||||
|
@ -44,26 +45,20 @@ Future<io.File> getFile(ente.File file) async {
|
|||
}
|
||||
}
|
||||
|
||||
Future<io.File> _getLocalDiskFile(ente.File file) async {
|
||||
if (file.isCachedInAppSandbox()) {
|
||||
var localPath = file.localID.replaceAll(RegExp(r'ente-upload-cache:'), '');
|
||||
return io.File(localPath);
|
||||
} else {
|
||||
return await (await file.getAsset()).file;
|
||||
}
|
||||
}
|
||||
|
||||
void preloadThumbnail(ente.File file) {
|
||||
if (file.isRemoteFile()) {
|
||||
getThumbnailFromServer(file);
|
||||
} else {
|
||||
if (ThumbnailLruCache.get(file, THUMBNAIL_SMALL_SIZE) != null) {
|
||||
return;
|
||||
}
|
||||
file.getAsset().then((asset) {
|
||||
if (asset != null) {
|
||||
asset
|
||||
.thumbDataWithSize(
|
||||
THUMBNAIL_SMALL_SIZE,
|
||||
THUMBNAIL_SMALL_SIZE,
|
||||
quality: THUMBNAIL_QUALITY,
|
||||
)
|
||||
.then((data) {
|
||||
ThumbnailLruCache.put(file, data, THUMBNAIL_SMALL_SIZE);
|
||||
});
|
||||
}
|
||||
});
|
||||
getThumbnailFromLocal(file);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,11 +131,11 @@ Future<io.File> _downloadAndDecrypt(
|
|||
var fileExtension = "unknown";
|
||||
try {
|
||||
fileExtension = extension(file.title).substring(1).toLowerCase();
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
_logger.severe("Could not capture file extension");
|
||||
}
|
||||
var outputFile = decryptedFile;
|
||||
if ((fileExtension=="unknown" && file.fileType == FileType.image) ||
|
||||
if ((fileExtension == "unknown" && file.fileType == FileType.image) ||
|
||||
(io.Platform.isAndroid && fileExtension == "heic")) {
|
||||
outputFile = await FlutterImageCompress.compressAndGetFile(
|
||||
decryptedFilePath,
|
||||
|
@ -156,6 +151,11 @@ Future<io.File> _downloadAndDecrypt(
|
|||
maxAge: Duration(days: 365),
|
||||
fileExtension: fileExtension,
|
||||
);
|
||||
_logger.info("File Put in cacheManager " +
|
||||
file.uploadedFileID.toString() +
|
||||
" " +
|
||||
cachedFile.uri.toString());
|
||||
|
||||
outputFile.deleteSync();
|
||||
fileDownloadsInProgress.remove(file.uploadedFileID);
|
||||
return cachedFile;
|
||||
|
|
|
@ -17,6 +17,8 @@ import 'package:photos/utils/file_util.dart';
|
|||
|
||||
import 'dart:io' as io;
|
||||
|
||||
import 'file_uploader_util.dart';
|
||||
|
||||
final _logger = Logger("ThumbnailUtil");
|
||||
final _map = LinkedHashMap<int, FileDownloadItem>();
|
||||
final _queue = Queue<int>();
|
||||
|
@ -57,6 +59,40 @@ Future<Uint8List> getThumbnailFromServer(File file) async {
|
|||
}
|
||||
}
|
||||
|
||||
Future<Uint8List> getThumbnailFromLocal(File file) async {
|
||||
if (ThumbnailLruCache.get(file, THUMBNAIL_SMALL_SIZE) != null) {
|
||||
return ThumbnailLruCache.get(file);
|
||||
}
|
||||
final cachedThumbnail = getCachedThumbnail(file);
|
||||
if (cachedThumbnail.existsSync()) {
|
||||
final data = cachedThumbnail.readAsBytesSync();
|
||||
ThumbnailLruCache.put(file, data);
|
||||
return data;
|
||||
}
|
||||
if (file.isCachedInAppSandbox()) {
|
||||
return getThumbnailFromInAppCacheFile(file)
|
||||
.then((data) {
|
||||
if (data != null) {
|
||||
ThumbnailLruCache.put(file, data, THUMBNAIL_SMALL_SIZE);
|
||||
}
|
||||
return data;
|
||||
});
|
||||
} else {
|
||||
return file.getAsset().then((asset) async {
|
||||
if (asset == null || !(await asset.exists)) {
|
||||
return null;
|
||||
}
|
||||
return asset
|
||||
.thumbDataWithSize(THUMBNAIL_SMALL_SIZE, THUMBNAIL_SMALL_SIZE,
|
||||
quality: THUMBNAIL_QUALITY)
|
||||
.then((data) {
|
||||
ThumbnailLruCache.put(file, data, THUMBNAIL_SMALL_SIZE);
|
||||
return data;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void removePendingGetThumbnailRequestIfAny(File file) {
|
||||
if (_map.containsKey(file.uploadedFileID)) {
|
||||
final item = _map[file.uploadedFileID];
|
||||
|
@ -132,5 +168,6 @@ Future<void> _downloadAndDecryptThumbnail(FileDownloadItem item) async {
|
|||
io.File getCachedThumbnail(File file) {
|
||||
final thumbnailCacheDirectory =
|
||||
Configuration.instance.getThumbnailCacheDirectory();
|
||||
return io.File(thumbnailCacheDirectory + "/" + file.uploadedFileID.toString());
|
||||
}
|
||||
return io.File(
|
||||
thumbnailCacheDirectory + "/" + file.uploadedFileID.toString());
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue