localFile function
Implementation
Future<File> localFile(String name, [String? doc]) async {
name = _canonicalizeScopedName(name);
// allow nested relative paths (e.g. per inspection) and create dirs if needed
final basePath = await localPath;
var p0 = File('$basePath/$name');
// keep legacy behaviour only for flat names; otherwise preserve folders
final hasFolder = name.contains('/');
String? legacyName;
if (hasFolder) {
final parts = name.split('/');
final scope = _canonicalizeScope(parts.first);
await _mergeLegacyScopeIntoCanonical(scope);
final legacyScope = _legacyScopeForCanonical(scope);
if (legacyScope != scope) {
legacyName = [legacyScope, ...parts.skip(1)].join('/');
}
}
Future<File?> migrateLegacyFileIfPresent() async {
if (legacyName == null || legacyName.isEmpty) return null;
final legacyFile = File('$basePath/$legacyName');
if (!legacyFile.existsSync()) return null;
await p0.parent.create(recursive: true);
if (!p0.existsSync()) {
await legacyFile.copy(p0.path);
}
try {
await legacyFile.delete();
} catch (_) {}
return p0;
}
if (doc != null) {
final migrated = await migrateLegacyFileIfPresent();
if (migrated != null) return migrated;
await p0.parent.create(recursive: true);
return p0;
}
if (await p0.exists()) return p0;
final migrated = await migrateLegacyFileIfPresent();
if (migrated != null) return migrated;
if (hasFolder) {
// if the file has no extension, prefer a .jpg to keep it recognizable
final baseName = p0.uri.pathSegments.last;
if (!baseName.contains('.')) {
final withExt = File('$basePath/$name.jpg');
return withExt;
}
await p0.parent.create(recursive: true);
return p0;
}
final sanitized =
name.replaceAll(RegExp(r'[^\w]+'), '_'); // legacy naming fallback
final p1 = File('$basePath/$sanitized.img');
if (await p1.exists() || useOldImgEncoding) {
await p1.parent.create(recursive: true);
return p1;
}
final p2 = File('$basePath/$sanitized.maybe.jpg');
await p2.parent.create(recursive: true);
return p2;
}