uploadFiles function

Future<void> uploadFiles({
  1. required BuildContext context,
  2. required FileUploadAction action,
  3. required DataContext dataContext,
  4. ScopeManager? scopeManager,
  5. Map<String, YamlMap>? apiMap,
})

Implementation

Future<void> uploadFiles({
  required BuildContext context,
  required FileUploadAction action,
  required DataContext dataContext,
  ScopeManager? scopeManager,
  Map<String, YamlMap>? apiMap,
}) async {
  List<File>? selectedFiles = _getRawFiles(action.files, dataContext);

  if (selectedFiles == null) {
    if (action.onError != null) {
      ScreenController().executeAction(context, action.onError!);
    }
    return;
  }

  if (isFileSizeOverLimit(context, dataContext, selectedFiles, action)) {
    if (action.onError != null) {
      ScreenController().executeAction(context, action.onError!);
    }
    return;
  }

  if (action.id != null && scopeManager != null) {
    final uploadFilesResponse =
        scopeManager.dataContext.getContextById(action.id!);
    scopeManager.dataContext.addInvokableContext(
        action.id!,
        (uploadFilesResponse is UploadFilesResponse)
            ? uploadFilesResponse
            : UploadFilesResponse());
  }

  final apiDefinition = apiMap?[action.uploadApi];
  if (apiDefinition == null) {
    throw LanguageError(
        'Unable to find api definition for ${action.uploadApi}');
  }

  if (apiDefinition['inputs'] is YamlList && action.inputs != null) {
    for (var input in apiDefinition['inputs']) {
      final value = dataContext.eval(action.inputs![input]);
      if (value != null) {
        dataContext.addDataContextById(input, value);
      }
    }
  }

  Map<String, String> headers = {};
  if (apiDefinition['headers'] is YamlMap) {
    (apiDefinition['headers'] as YamlMap).forEach((key, value) {
      if (value != null) {
        headers[key.toString()] = dataContext.eval(value).toString();
      }
    });
  }

  Map<String, String> fields = {};
  if (apiDefinition['body'] is YamlMap) {
    (apiDefinition['body'] as YamlMap).forEach((key, value) {
      if (value != null) {
        fields[key.toString()] = dataContext.eval(value).toString();
      }
    });
  }
  String rawUrl = apiDefinition['url']?.toString().trim() ??
      apiDefinition['uri']?.toString().trim() ??
      '';

  String url = HTTPAPIProvider.resolveUrl(dataContext, rawUrl);
  String method = apiDefinition['method']?.toString().toUpperCase() ?? 'POST';
  final fileResponse = action.id == null
      ? null
      : scopeManager?.dataContext.getContextById(action.id!)
          as UploadFilesResponse;

  final fileBatches =
      splitUploadFileBatches(selectedFiles, action.batchSize);

  for (var fileBatch in fileBatches) {
    if (action.isBackgroundTask) {
      if (kIsWeb) {
        throw LanguageError('Background Upload is not supported on web');
      }
      await _setBackgroundUploadTask(
        context: context,
        action: action,
        selectedFiles: fileBatch,
        headers: headers,
        fields: fields,
        method: method,
        url: url,
        fileResponse: fileResponse,
        scopeManager: scopeManager,
      );

      continue;
    }
    final taskId = Utils.generateRandomId(8);
    fileResponse?.addTask(UploadTask(id: taskId));

    final response = await UploadUtils.uploadFiles(
      headers: headers,
      fields: fields,
      method: method,
      url: url,
      files: fileBatch,
      fieldName: action.fieldName,
      showNotification: action.showNotification,
      onError: action.onError == null
          ? null
          : (error) =>
              ScreenController().executeAction(context, action.onError!),
      progressCallback: (progress) {
        if (action.id == null) return;
        fileResponse?.setProgress(taskId, progress);
        scopeManager?.dispatch(
            ModelChangeEvent(APIBindingSource(action.id!), fileResponse));
      },
      taskId: taskId,
    );

    if (response == null) {
      fileResponse?.setStatus(taskId, UploadStatus.failed);
      return;
    }
    fileResponse?.setHeaders(taskId, response.headers);
    fileResponse?.setBody(taskId, response.body);
    fileResponse?.setStatus(taskId, UploadStatus.completed);
    scopeManager?.dispatch(
        ModelChangeEvent(APIBindingSource(action.id!), fileResponse));

    if (action.onComplete != null) {
      // TODO: @snehmehta, fix this
      ScreenController().executeAction(context, action.onComplete!);
    }
  }
}