createFolderRecursive method

Future<Map<String, dynamic>> createFolderRecursive(
  1. String path, {
  2. String? creationTime,
  3. String? modificationTime,
})

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;
}