getImageByHash method
Implementation
Future<ImageData?> getImageByHash(String hash, {Data? owner}) async {
final isPath = hash.contains('/');
final scope = _scopeForData(owner);
final legacyScope = scope.contains('undefined')
? scope.replaceAll('undefined', 'null')
: scope;
String displayNameFromStored(String storedName) {
var base = storedName.split('/').where((e) => e.isNotEmpty).toList().last;
// strip prefixes
if (base.startsWith(LOCALLY_ADDED_PREFIX)) {
base = base.substring(LOCALLY_ADDED_PREFIX.length);
}
// strip common extensions
final lower = base.toLowerCase();
const suffixes = [
'.maybe.jpg',
'.img',
'.jpeg',
'.jpg',
'.webp',
'.heic',
'.png',
];
for (final s in suffixes) {
if (lower.endsWith(s)) {
return base.substring(0, base.length - s.length);
}
}
final dot = base.lastIndexOf('.');
if (dot > 0 && dot > base.length - 8) return base.substring(0, dot);
return base;
}
// Prefer the backend filename-based cache if present.
if (!isPath) {
try {
final indexed = await OP.lookupImageNameForHash(
hash,
scope: scope,
);
if (indexed != null && indexed.isNotEmpty) {
final img = await readImage(indexed, cacheSize: null);
if (img != null)
return ImageData(img,
id: hash, name: displayNameFromStored(indexed));
}
} catch (_) {}
}
List<String> candidates = [];
if (!isPath && scope.isNotEmpty) {
final scoped = '$scope/$hash';
candidates.add(scoped);
}
if (!isPath && legacyScope.isNotEmpty && legacyScope != scope) {
final scoped = '$legacyScope/$hash';
candidates.add(scoped);
}
candidates.add(hash);
for (final name in candidates) {
final img = await readImage(name, cacheSize: null);
if (img != null) {
// Best-effort migration: if we loaded from a legacy "null" folder, copy to the
// canonical "undefined" folder so we stop accumulating both.
if (!isPath &&
scope.isNotEmpty &&
legacyScope != scope &&
name.startsWith('$legacyScope/')) {
final migratedName = name.replaceFirst(legacyScope, scope);
try {
final src = await OP.localFile(name);
final dst = await OP.localFile(migratedName);
if (!dst.existsSync()) {
await dst.parent.create(recursive: true);
await src.copy(dst.path);
}
await OP.indexImageHash(
hash: hash,
storedName: migratedName,
scope: scope,
);
final migratedImg = await readImage(migratedName, cacheSize: null);
if (migratedImg != null) {
return ImageData(migratedImg,
id: hash, name: displayNameFromStored(migratedName));
}
} catch (_) {}
}
return ImageData(img, id: hash, name: displayNameFromStored(name));
}
}
throw Exception("no img cached");
}