createFolderRecursive method
Implementation
Future<Map<String, dynamic>> createFolderRecursive(String path,
{String? creationTime, String? modificationTime}) async {
if (baseFolderUUID.isEmpty) throw Exception("Not logged in");
var cleanPath = path.trim().replaceAll(RegExp(r'^/+|/+$'), '');
if (cleanPath.isEmpty) {
return {'uuid': baseFolderUUID, 'plainName': 'Root', 'path': '/'};
}
if (cache.pathCache.containsKey(cleanPath)) {
return cache.pathCache[cleanPath]!;
}
var parts = cleanPath.split('/');
var currentParentUuid = baseFolderUUID;
var currentPath = '/';
Map<String, dynamic> currentFolderInfo = {
'uuid': baseFolderUUID,
'plainName': 'Root',
'path': '/'
};
for (var i = 0; i < parts.length; i++) {
final part = parts[i];
if (part.isEmpty) continue;
final isLastPart = (i == parts.length - 1);
final partPathStr = '$currentPath$part/'.replaceAll('//', '/');
final cleanPartPath = partPathStr.replaceAll(RegExp(r'/$'), '');
if (cache.pathCache.containsKey(cleanPartPath)) {
currentFolderInfo = cache.pathCache[cleanPartPath]!;
currentParentUuid = currentFolderInfo['uuid'];
currentPath = partPathStr;
continue;
}
final folders = await cache.listFoldersAsync(currentParentUuid,
api: api, crypto: crypto, masterKeys: masterKeys);
Map<String, dynamic>? found;
for (var folder in folders) {
if (folder['name'] == part) {
found = folder;
break;
}
}
if (found != null) {
currentParentUuid = found['uuid'];
currentFolderInfo = found;
currentFolderInfo['path'] = cleanPartPath;
currentPath = partPathStr;
cache.pathCache[cleanPartPath] = currentFolderInfo;
} else {
api.log("Creating folder: $part in $currentPath");
try {
await createDirectory(
part,
currentParentUuid,
creationTime: isLastPart ? creationTime : null,
modificationTime: isLastPart ? modificationTime : null,
);
} catch (e) {
if (e.toString().contains('409') ||
e.toString().contains('already exists')) {
api.log('Conflict (409), re-fetching...');
await Future.delayed(Duration(milliseconds: 500));
cache.invalidate(currentParentUuid);
} else {
throw e;
}
}
await Future.delayed(Duration(milliseconds: 200));
cache.invalidate(currentParentUuid);
final foldersAfter = await cache.listFoldersAsync(currentParentUuid,
api: api, crypto: crypto, masterKeys: masterKeys);
Map<String, dynamic>? newFolder;
for (var f in foldersAfter) {
if (f['name'] == part) {
newFolder = f;
break;
}
}
if (newFolder == null)
throw Exception("Created folder but couldn't find it: $part");
currentParentUuid = newFolder['uuid'];
currentFolderInfo = newFolder;
currentFolderInfo['path'] = cleanPartPath;
currentPath = partPathStr;
cache.pathCache[cleanPartPath] = currentFolderInfo;
}
}
return currentFolderInfo;
}