Simplify metadata loader

No reason for the metadata loader to handle the downloading
This commit is contained in:
Ming Ming 2021-07-13 12:32:05 +08:00
parent 76bc61c155
commit 1f49c2d3ea
6 changed files with 19 additions and 145 deletions

View file

@ -1,79 +0,0 @@
import 'dart:async';
import 'package:exifdart/exifdart_io.dart';
import 'package:exifdart/exifdart_memory.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:logging/logging.dart';
import 'package:nc_photos/account.dart';
import 'package:nc_photos/api/api.dart';
import 'package:nc_photos/api/api_util.dart' as api_util;
import 'package:nc_photos/cache_manager_util.dart';
import 'package:nc_photos/entity/file.dart';
import 'package:nc_photos/exception.dart';
import 'package:nc_photos/image_size_getter_util.dart';
import 'package:nc_photos/platform/metadata_loader.dart' as itf;
class MetadataLoader implements itf.MetadataLoader {
@override
loadCacheFile(Account account, File file) async {
final getFileFuture =
_getFileTask.getFileUntil(api_util.getFileUrl(account, file));
final result = await Future.any([
getFileFuture,
Future.delayed(Duration(seconds: 10)),
]);
if (_getFileTask.isGood && result is FileInfo) {
return _onGetFile(file, result);
} else {
// timeout
_getFileTask.cancel();
throw TimeoutException("Timeout loading file: ${file.strippedPath}");
}
}
@override
loadNewFile(Account account, File file) async {
final response =
await Api(account).files().get(path: api_util.getFileUrlRelative(file));
if (!response.isGood) {
_log.severe("[loadNewFile] Failed requesting server: $response");
throw ApiException(
response: response,
message: "Failed communicating with server: ${response.statusCode}");
}
return itf.MetadataLoader.loadMetadata(
file: file,
exifdartReaderBuilder: () => MemoryBlobReader(response.body),
imageSizeGetterInputBuilder: () => AsyncMemoryInput(response.body),
);
}
@override
loadFile(Account account, File file) async {
final store = DefaultCacheManager().store;
final info = await store.getFile(api_util.getFileUrl(account, file));
if (info == null) {
// no cache
return loadNewFile(account, file);
} else {
return _onGetFile(file, info);
}
}
@override
cancel() {
_getFileTask.cancel();
}
Future<Map<String, dynamic>> _onGetFile(File file, FileInfo info) {
return itf.MetadataLoader.loadMetadata(
file: file,
exifdartReaderBuilder: () => FileReader(info.file),
imageSizeGetterInputBuilder: () => AsyncFileInput(info.file),
);
}
final _getFileTask = CancelableGetFile(DefaultCacheManager().store);
static final _log = Logger("mobile.metadata_loader.MetadataLoader");
}

View file

@ -1,5 +1,4 @@
export 'db_util.dart';
export 'downloader.dart';
export 'map_widget.dart';
export 'metadata_loader.dart';
export 'universal_storage.dart';

View file

@ -1,30 +1,26 @@
import 'dart:typed_data';
import 'package:exifdart/exifdart.dart' as exifdart;
import 'package:exifdart/exifdart_memory.dart';
import 'package:flutter/foundation.dart';
import 'package:image_size_getter/image_size_getter.dart';
import 'package:nc_photos/account.dart';
import 'package:nc_photos/entity/file.dart';
import 'package:nc_photos/entity/file_util.dart' as file_util;
import 'package:nc_photos/image_size_getter_util.dart';
abstract class MetadataLoader {
/// Load metadata for [file] from cache
///
/// If the file is not found in cache after a certain amount of time, an
/// exception will be thrown
Future<Map<String, dynamic>> loadCacheFile(Account account, File file);
class LoadMetadata {
/// Load metadata of [binary], which is the content of [file]
Future<Map<String, dynamic>> call(
Account account, File file, Uint8List binary) {
return _loadMetadata(
file: file,
exifdartReaderBuilder: () => MemoryBlobReader(binary),
imageSizeGetterInputBuilder: () => AsyncMemoryInput(binary),
);
}
/// Download and load metadata for [file]
///
/// This function will always try to download the file, no matter it's cached
/// or not
Future<Map<String, dynamic>> loadNewFile(Account account, File file);
/// Load metadata for [file], either from cache or a new download
Future<Map<String, dynamic>> loadFile(Account account, File file);
void cancel();
@protected
static Future<Map<String, dynamic>> loadMetadata({
Future<Map<String, dynamic>> _loadMetadata({
@required File file,
exifdart.AbstractBlobReader Function() exifdartReaderBuilder,
AsyncImageInput Function() imageSizeGetterInputBuilder,

View file

@ -4,9 +4,9 @@ import 'package:nc_photos/connectivity_util.dart' as connectivity_util;
import 'package:nc_photos/entity/exif.dart';
import 'package:nc_photos/entity/file.dart';
import 'package:nc_photos/entity/file/data_source.dart';
import 'package:nc_photos/mobile/platform.dart'
if (dart.library.html) 'package:nc_photos/web/platform.dart' as platform;
import 'package:nc_photos/or_null.dart';
import 'package:nc_photos/use_case/get_file_binary.dart';
import 'package:nc_photos/use_case/load_metadata.dart';
import 'package:nc_photos/use_case/scan_missing_metadata.dart';
import 'package:nc_photos/use_case/update_property.dart';
@ -19,7 +19,6 @@ class UpdateMissingMetadata {
/// would emit either File data (for each updated files) or an exception
Stream<dynamic> call(Account account, File root) async* {
final dataStream = ScanMissingMetadata(fileRepo)(account, root);
final metadataLoader = platform.MetadataLoader();
await for (final d in dataStream) {
if (d is Exception || d is Error) {
yield d;
@ -34,7 +33,8 @@ class UpdateMissingMetadata {
return;
}
_log.fine("[call] Updating metadata for ${file.path}");
final metadata = await metadataLoader.loadFile(account, file);
final binary = await GetFileBinary(fileRepo)(account, file);
final metadata = await LoadMetadata()(account, file, binary);
int imageWidth, imageHeight;
Exif exif;
if (metadata.containsKey("resolution")) {

View file

@ -1,41 +0,0 @@
import 'package:exifdart/exifdart_memory.dart';
import 'package:logging/logging.dart';
import 'package:nc_photos/account.dart';
import 'package:nc_photos/api/api.dart';
import 'package:nc_photos/api/api_util.dart' as api_util;
import 'package:nc_photos/entity/file.dart';
import 'package:nc_photos/exception.dart';
import 'package:nc_photos/image_size_getter_util.dart';
import 'package:nc_photos/platform/metadata_loader.dart' as itf;
class MetadataLoader implements itf.MetadataLoader {
// on web we just download the image again, hopefully the browser would
// cache it for us (which is sadly not the case :|
@override
loadCacheFile(Account account, File file) => loadNewFile(account, file);
@override
loadNewFile(Account account, File file) async {
final response =
await Api(account).files().get(path: api_util.getFileUrlRelative(file));
if (!response.isGood) {
_log.severe("[loadFile] Failed requesting server: $response");
throw ApiException(
response: response,
message: "Failed communicating with server: ${response.statusCode}");
}
return itf.MetadataLoader.loadMetadata(
file: file,
exifdartReaderBuilder: () => MemoryBlobReader(response.body),
imageSizeGetterInputBuilder: () => AsyncMemoryInput(response.body),
);
}
@override
loadFile(Account account, File file) => loadNewFile(account, file);
@override
cancel() {}
static final _log = Logger("web.metadata_loader.MetadataLoader");
}

View file

@ -1,5 +1,4 @@
export 'db_util.dart';
export 'downloader.dart';
export 'map_widget.dart';
export 'metadata_loader.dart';
export 'universal_storage.dart';