Cloud
Add files and folders

Add files and folders

In this section we'll look at different ways of adding files and folders to the cloud.

Upload a file from device

The secrecyClient.cloud.uploadDataInCloud method is designed to upload a file to the cloud. You can optionally add it to a specific location in the cloud or to its root. We recommand for checking for duplicate file names before uploading a file as we do in the example below.

cloud.ts
import { checkHasNodeName, renameNode } from '/utils';
 
const handleAddFileToCloud = async (
  file: File,
  // corresponds to the selected parent file id
  nodeParentId?: string
): Promise<NodeFull | null> => {
  // First we need to check if the secrecyClient is available
  if (!secrecyClient) {
    return null;
  }
 
  //  If a parent folder is selected, check if another file with the same name is present in the parent folder, otherwise in the root folder.
  const name = checkHasNodeName(file.name)
    ? checkHasNodeName(file.name)
    : file.name;
 
  try {
    const node = await secrecyClient.cloud.uploadDataInCloud({
      data: file,
      name: name,
      // If nodeParentId is provided, the file will be added just below the parent folder. Otherwise, it will be added to the root of the tree.
      nodeId: nodeParentId,
    });
    return node;
  } catch (error) {
    console.error(error);
    return null;
  }
};

Create a new folder in the cloud

The secrecyClient.cloud.createFolder method is designed to add a new folder int the cloud. You can optionally add it to a specific location in the cloud or to its root. We recommand for checking for duplicate file names before uploading a file as we do in the example below.

cloud.ts
import { checkHasNodeName, renameNode } from '/utils';
 
const addNewFolderInCloud = async (
  folderName: string,
  // corresponds to the selected parent file id
  nodeParentId?: string
): Promise<NodeFull | null> => {
  // First we need to check if the secrecyClient is available
  if (!secrecyClient) {
    return null;
  }
 
  //  If a parent folder is selected, check if another file with the same name is present in the parent folder, otherwise in the root folder.
  const name = checkHasNodeName(folderName)
    ? renameNode(folderName)
    : folderName;
 
  try {
    const node = await secrecyClient.cloud.createFolder({
      name: name,
      parentFolderId: nodeParentId,
    });
    return node;
  } catch (error) {
    console.error(error);
    return null;
  }
};

Import a folder from device

The function shown below is an example handleAddFolderToCloud of how these two methods secrecyClient.cloud.uploadDataInCloud and secrecyClient.cloud.createFolder can be combined for a common use case. It handles the process of uploading a file list (including files and folders) to the cloud. It organizes files and folders from the input fileList, ensuring that folder hierarchies are preserved and preventing naming conflicts by checking for duplicates.

cloud.ts
import { verifSameName } from '/utils';
 
interface ContentDefault {
  fullPath?: string;
  name: string;
  type: 'file' | 'folder';
  parentId?: string;
  id: string;
}
 
interface FileContent extends ContentDefault {
  file: File;
  type: 'file';
}
 
interface FolderContent extends ContentDefault {
  type: 'folder';
}
 
const handleAddFolderToCloud = async ({
  fileList,
  folderId,
  folder,
}: {
  fileList: FileList;
  folderId: string;
  folder?: NodeFull;
}): Promise<void> => {
  const { client } = getUserState();
  if (!client) {
    throw 'No client';
  }
  const files: FileContent[] = [];
  const folders: FolderContent[] = [];
 
  for (const file of fileList) {
    if (file.webkitRelativePath) {
      const foldersSplit = file.webkitRelativePath.split('/').slice(0, -1);
      let idFolderParent = '';
 
      for (
        let indexFolderSplit = 0;
        indexFolderSplit < foldersSplit.length;
        indexFolderSplit++
      ) {
        const folderSplit = foldersSplit[indexFolderSplit];
        const fullPath = foldersSplit.slice(0, indexFolderSplit + 1).join('/');
        const id = fullPath;
 
        folders.push({
          id: id,
          name: folderSplit ?? '',
          type: 'folder',
          fullPath: fullPath,
          parentId: idFolderParent,
        });
 
        idFolderParent = id;
      }
 
      files.push({
        file: file,
        id: nanoid(),
        name: file.name,
        type: 'file',
        parentId: foldersSplit.join('/'),
      });
 
      continue;
    }
 
    files.push({
      file: file,
      id: nanoid(),
      name: file.name,
      type: 'file',
    });
  }
 
  const folderFiltered: FolderContent[] = [];
  for (const folder of folders) {
    if (!folderFiltered.some((item) => item.id === folder.id)) {
      folderFiltered.push(folder);
    }
  }
  const groupId = nanoid();
 
  // Get sameName
  const moveSameName = await verifSameName({
    nodeList: [...files, ...folders].map((item) => ({
      name: item.name,
      id: item.id,
    })),
    parentFolderId: folderId,
    folder: folder,
  });
 
  // ------ RENAME -------
  // Set sameName
  const filesRenamed = files.map((item) => {
    const nodeSameName = moveSameName?.nodesSameName.find(
      (node) => node.node.id === item.id
    );
 
    if (nodeSameName) {
      return {
        ...item,
        name: nodeSameName.newName,
      };
    }
    return item;
  });
 
  const folderRenamed = folders.map((item) => {
    const foldersSameName = moveSameName?.nodesSameName.find(
      (node) => node.node.id === item.id
    );
 
    if (foldersSameName) {
      return {
        ...item,
        name: foldersSameName.newName,
      };
    }
    return item;
  });
 
  // ------ FILTER -------
  // Filtered folders
  const foldersFiltered = folderRenamed;
 
  // Filtered files
  const filesFiltered = filesRenamed.filter((item) => {
    // Remove .DS_Store
    if (item.name === '.DS_Store') {
      return false;
    }
    return true;
  });
 
  // ------ FORMAT -------
  // Format folders
  let foldersFormated = foldersFiltered.map((item) => {
    return {
      ...item,
      parentCloudId: !item.parentId ? folderId : undefined,
    };
  });
 
  // Format files
  let filesFormated = filesFiltered.map((item) => {
    return {
      ...item,
      parentCloudId: !item.parentId ? folderId : undefined,
    };
  });
 
  // ------ UPLOAD -------
  // Upload folders
  for (const folder of foldersFormated) {
    const newFolder = await client.cloud.createFolder({
      name: folder.name,
      parentFolderId: folder.parentCloudId ?? folderId,
    });
 
    // Change parent cloud id in folders
    foldersFormated = foldersFormated.map((item) => {
      if (item.parentId === folder.id) {
        return {
          ...item,
          parentCloudId: newFolder?.id,
        };
      }
 
      return item;
    });
 
    // Change parent cloud id in files
    filesFormated = filesFormated.map((item) => {
      if (item.parentId === folder.id) {
        return {
          ...item,
          parentCloudId: newFolder?.id,
        };
      }
 
      return item;
    });
  }
  // Upload files
  for (const file of filesFormated) {
    void client.cloud.uploadDataInCloud({
      data: file.file,
      name: file.name,
      nodeId: file.parentCloudId ?? '',
    });
  }
};