diff --git a/packages/common-components/rollup.config.js b/packages/common-components/rollup.config.js index cf32c5eaa8..b9323226bb 100644 --- a/packages/common-components/rollup.config.js +++ b/packages/common-components/rollup.config.js @@ -20,7 +20,7 @@ export default { plugins: [ peerDepsExternal(), image(), - resolve(), + resolve({ browser: true }), commonjs(), typescript(), postcss({ diff --git a/packages/common-components/src/TextInput/TextInput.tsx b/packages/common-components/src/TextInput/TextInput.tsx index ae4454bf60..e78705b14b 100644 --- a/packages/common-components/src/TextInput/TextInput.tsx +++ b/packages/common-components/src/TextInput/TextInput.tsx @@ -72,6 +72,7 @@ const useStyles = makeStyles( "&.disabled": { "& input": { color: palette.additional["gray"][6], + "-webkit-text-fill-color": palette.additional["gray"][6], backgroundColor: palette.additional["gray"][3], ...overrides?.TextInput?.input?.disabled }, diff --git a/packages/common-components/src/Toasts/ToastContent.tsx b/packages/common-components/src/Toasts/ToastContent.tsx index 74fc98ccc5..5f74826548 100644 --- a/packages/common-components/src/Toasts/ToastContent.tsx +++ b/packages/common-components/src/Toasts/ToastContent.tsx @@ -7,7 +7,7 @@ import { CheckCircleIcon, CloseCircleIcon, CloseCirceSvg, CrossSvg } from "../Ic import { ProgressBar } from "../ProgressBar" import { Loading } from "../Spinner" -const useStyles = makeStyles(({ constants, palette, animation, overrides }: ITheme) => { +const useStyles = makeStyles(({ constants, palette, overrides }: ITheme) => { return createStyles({ root: { backgroundColor: palette.additional["gray"][3], @@ -16,10 +16,6 @@ const useStyles = makeStyles(({ constants, palette, animation, overrides }: IThe padding: constants.generalUnit * 2, borderRadius: 4, position: "relative", - "&:hover $closeIcon": { - visibility: "visible", - opacity: 1 - }, ...overrides?.Toasts?.root }, progressBox: { @@ -66,9 +62,6 @@ const useStyles = makeStyles(({ constants, palette, animation, overrides }: IThe backgroundColor: palette.additional["gray"][1], border: "1px solid", borderColor: palette.additional["gray"][9], - opacity: 0, - visibility: "hidden", - transition: `opacity ${animation.transform}ms`, display: "flex", alignItems: "center", justifyContent: "center", @@ -147,6 +140,7 @@ const ToastContent = ({ toast, onClose }: ToastContentProps) => { } {isClosable &&
diff --git a/packages/files-ui/cypress/support/page-objects/binPage.ts b/packages/files-ui/cypress/support/page-objects/binPage.ts index 7b8f48429b..afb126f1c3 100644 --- a/packages/files-ui/cypress/support/page-objects/binPage.ts +++ b/packages/files-ui/cypress/support/page-objects/binPage.ts @@ -8,7 +8,6 @@ export const binPage = { // bin page specific file browser elements recoverSelectedButton: () => cy.get("[data-testId=button-recover-selected-file]"), deleteSelectedButton: () => cy.get("[data-testId=button-delete-selected-file]"), - permanentDeleteSuccessToast: () => cy.get("[data-testId=toast-deletion-success]", { timeout: 10000 }), selectAllCheckbox: () => cy.get("[data-testId=checkbox-select-all]"), // kebab menu elements diff --git a/packages/files-ui/cypress/support/page-objects/homePage.ts b/packages/files-ui/cypress/support/page-objects/homePage.ts index 87a161e0a3..cbfd7d260c 100644 --- a/packages/files-ui/cypress/support/page-objects/homePage.ts +++ b/packages/files-ui/cypress/support/page-objects/homePage.ts @@ -1,6 +1,7 @@ import { basePage } from "./basePage" import { fileBrowser } from "./fileBrowser" import { fileUploadModal } from "./modals/fileUploadModal" +import { uploadCompleteToast } from "./toasts/uploadCompleteToast" export const homePage = { ...basePage, @@ -12,8 +13,6 @@ export const homePage = { moveSelectedButton: () => cy.get("[data-testId=button-move-selected-file]"), deleteSelectedButton: () => cy.get("[data-testId=button-delete-selected-file]"), selectAllCheckbox: () => cy.get("[data-testId=checkbox-select-all]"), - uploadStatusToast: () => cy.get("[data-testId=toast-upload-status]", { timeout: 10000 }), - deleteSuccessToast: () => cy.get("[data-testId=toast-deletion-success]", { timeout: 10000 }), fileRenameInput: () => cy.get("[data-cy=rename-form] input"), fileRenameSubmitButton: () => cy.get("[data-cy=rename-submit-button]"), fileRenameErrorLabel: () => cy.get("[data-cy=rename-form] span.minimal.error"), @@ -36,7 +35,8 @@ export const homePage = { // ensure upload is complete before proceeding fileUploadModal.body().should("not.exist") - this.uploadStatusToast().should("not.exist") + uploadCompleteToast.body().should("be.visible") + uploadCompleteToast.closeButton().click() } } diff --git a/packages/files-ui/cypress/support/page-objects/toasts/deleteSuccessToast.ts b/packages/files-ui/cypress/support/page-objects/toasts/deleteSuccessToast.ts new file mode 100644 index 0000000000..223017ff80 --- /dev/null +++ b/packages/files-ui/cypress/support/page-objects/toasts/deleteSuccessToast.ts @@ -0,0 +1,4 @@ +export const deleteSuccessToast = { + body: () => cy.get("[data-testId=toast-deletion-success]", { timeout: 10000 }), + closeButton: () => cy.get("[data-testid=button-close-toast-deletion-success]") +} diff --git a/packages/files-ui/cypress/support/page-objects/toasts/moveSuccessToast.ts b/packages/files-ui/cypress/support/page-objects/toasts/moveSuccessToast.ts new file mode 100644 index 0000000000..97e78d1707 --- /dev/null +++ b/packages/files-ui/cypress/support/page-objects/toasts/moveSuccessToast.ts @@ -0,0 +1,4 @@ +export const moveSuccessToast = { + body: () => cy.get("[data-testId=toast-move-success]", { timeout: 10000 }), + closeButton: () => cy.get("[data-testid=button-close-toast-move-success]") +} diff --git a/packages/files-ui/cypress/support/page-objects/toasts/uploadCompleteToast.ts b/packages/files-ui/cypress/support/page-objects/toasts/uploadCompleteToast.ts new file mode 100644 index 0000000000..632b2acbef --- /dev/null +++ b/packages/files-ui/cypress/support/page-objects/toasts/uploadCompleteToast.ts @@ -0,0 +1,4 @@ +export const uploadCompleteToast = { + body: () => cy.get("[data-testId=toast-upload-complete]", { timeout: 10000 }), + closeButton: () => cy.get("[data-testid=button-close-toast-upload-complete]") +} diff --git a/packages/files-ui/cypress/tests/file-management-spec.ts b/packages/files-ui/cypress/tests/file-management-spec.ts index fdabafa8ad..67025b40c9 100644 --- a/packages/files-ui/cypress/tests/file-management-spec.ts +++ b/packages/files-ui/cypress/tests/file-management-spec.ts @@ -9,6 +9,9 @@ import { deleteFileModal } from "../support/page-objects/modals/deleteFileModal" import { fileUploadModal } from "../support/page-objects/modals/fileUploadModal" import { moveItemModal } from "../support/page-objects/modals/moveItemModal" import { recoverItemModal } from "../support/page-objects/modals/recoverItemModal" +import { deleteSuccessToast } from "../support/page-objects/toasts/deleteSuccessToast" +import { moveSuccessToast } from "../support/page-objects/toasts/moveSuccessToast" +import { uploadCompleteToast } from "../support/page-objects/toasts/uploadCompleteToast" describe("File management", () => { @@ -81,6 +84,8 @@ describe("File management", () => { homePage.moveSelectedButton().click() moveItemModal.folderList().contains("Home").click() moveItemModal.moveButton().safeClick() + moveSuccessToast.body().should("be.visible") + moveSuccessToast.closeButton().click() // ensure the home root now has the folder and file navigationMenu.homeNavButton().click() @@ -174,6 +179,8 @@ describe("File management", () => { fileUploadModal.removeFileButton().should("have.length", 2) fileUploadModal.uploadButton().safeClick() fileUploadModal.body().should("not.exist") + uploadCompleteToast.body().should("be.visible") + uploadCompleteToast.closeButton().click() homePage.fileItemRow().should("have.length", 2) }) @@ -229,6 +236,8 @@ describe("File management", () => { deleteFileModal.body().should("be.visible") deleteFileModal.confirmButton().safeClick() deleteFileModal.body().should("not.exist") + deleteSuccessToast.body().should("be.visible") + deleteSuccessToast.closeButton().click() homePage.fileItemRow().should("not.exist") // confirm the deleted file is moved to the bin @@ -267,10 +276,14 @@ describe("File management", () => { homePage.fileItemKebabButton().first().click() homePage.deleteMenuOption().click() deleteFileModal.confirmButton().safeClick() + deleteSuccessToast.body().should("be.visible") + deleteSuccessToast.closeButton().click() navigationMenu.binNavButton().click() binPage.fileItemKebabButton().first().click() binPage.deleteMenuOption().click() deleteFileModal.confirmButton().safeClick() + deleteSuccessToast.body().should("be.visible") + deleteSuccessToast.closeButton().click() binPage.fileItemRow().should("not.exist") navigationMenu.homeNavButton().click() homePage.fileItemRow().should("not.exist") @@ -288,6 +301,8 @@ describe("File management", () => { deleteFileModal.body().should("be.visible") deleteFileModal.confirmButton().safeClick() deleteFileModal.body().should("not.exist") + deleteSuccessToast.body().should("be.visible") + deleteSuccessToast.closeButton().click() homePage.fileItemRow().should("not.exist") // confirm the deleted folder is moved to the bin @@ -312,10 +327,14 @@ describe("File management", () => { homePage.fileItemKebabButton().first().click() homePage.deleteMenuOption().click() deleteFileModal.confirmButton().safeClick() + deleteSuccessToast.body().should("be.visible") + deleteSuccessToast.closeButton().click() navigationMenu.binNavButton().click() binPage.fileItemKebabButton().first().click() binPage.deleteMenuOption().click() deleteFileModal.confirmButton().safeClick() + deleteSuccessToast.body().should("be.visible") + deleteSuccessToast.closeButton().click() binPage.fileItemRow().should("not.exist") navigationMenu.homeNavButton().click() homePage.fileItemRow().should("not.exist") @@ -366,12 +385,15 @@ describe("File management", () => { homePage.fileItemKebabButton().click() homePage.deleteMenuOption().click() deleteFileModal.confirmButton().safeClick() - homePage.deleteSuccessToast().should("not.exist") + deleteSuccessToast.body().should("be.visible") + deleteSuccessToast.closeButton().click() + navigationMenu.binNavButton().click() binPage.fileItemKebabButton().click() binPage.deleteMenuOption().click() deleteFileModal.confirmButton().safeClick() - binPage.permanentDeleteSuccessToast().should("not.exist") + deleteSuccessToast.body().should("be.visible") + deleteSuccessToast.closeButton().click() navigationMenu.spaceUsedLabel().should("contain.text", "0 Bytes") }) @@ -391,7 +413,8 @@ describe("File management", () => { homePage.selectAllCheckbox().click() homePage.deleteSelectedButton().click() deleteFileModal.confirmButton().safeClick() - homePage.deleteSuccessToast().should("not.exist") + deleteSuccessToast.body().should("be.visible") + deleteSuccessToast.closeButton().click() homePage.fileItemRow().should("have.length", 0) // recover both of the files in the same action diff --git a/packages/files-ui/cypress/tests/file-preview-spec.ts b/packages/files-ui/cypress/tests/file-preview-spec.ts index 0003413416..d20d5b53bf 100644 --- a/packages/files-ui/cypress/tests/file-preview-spec.ts +++ b/packages/files-ui/cypress/tests/file-preview-spec.ts @@ -72,7 +72,6 @@ describe("File Preview", () => { homePage.fileItemName().dblclick() previewModal.unsupportedFileLabel().should("exist") previewModal.downloadUnsupportedFileButton().should("be.visible") - // ensure the download request contains the correct file cy.get("@downloadRequest").its("request.body").should("contain", { path: "/file.zip" diff --git a/packages/files-ui/package.json b/packages/files-ui/package.json index 1d9af5079a..42b49f7131 100644 --- a/packages/files-ui/package.json +++ b/packages/files-ui/package.json @@ -6,7 +6,7 @@ "@babel/core": "^7.12.10", "@babel/runtime": "^7.0.0", "@chainsafe/browser-storage-hooks": "^1.0.1", - "@chainsafe/files-api-client": "^1.18.10", + "@chainsafe/files-api-client": "1.18.15", "@chainsafe/web3-context": "1.1.4", "@lingui/core": "^3.7.2", "@lingui/react": "^3.7.2", @@ -70,7 +70,7 @@ "@types/yup": "^0.29.9", "@types/zxcvbn": "^4.4.0", "babel-plugin-macros": "^2.8.0", - "cypress": "^8.4", + "cypress": "^8.6", "cypress-file-upload": "^5.0.8", "cypress-pipe": "^2.0.0" }, diff --git a/packages/files-ui/src/Components/Modules/FileBrowsers/BinFileBrowser.tsx b/packages/files-ui/src/Components/Modules/FileBrowsers/BinFileBrowser.tsx index ead6f7753f..516c3a6e19 100644 --- a/packages/files-ui/src/Components/Modules/FileBrowsers/BinFileBrowser.tsx +++ b/packages/files-ui/src/Components/Modules/FileBrowsers/BinFileBrowser.tsx @@ -7,7 +7,12 @@ import { t } from "@lingui/macro" import { CONTENT_TYPES } from "../../../Utils/Constants" import { IFilesTableBrowserProps } from "../../Modules/FileBrowsers/types" import { useHistory, useLocation, useToasts } from "@chainsafe/common-components" -import { extractFileBrowserPathFromURL, getPathWithFile, getUrlSafePathWithFile } from "../../../Utils/pathUtils" +import { + extractFileBrowserPathFromURL, + getAbsolutePathsFromCids, + getUrlSafePathWithFile, + pathEndingWithSlash +} from "../../../Utils/pathUtils" import { ROUTE_LINKS } from "../../FilesRoutes" import { FileBrowserContext } from "../../../Contexts/FileBrowserContext" import { useFilesApi } from "../../../Contexts/FilesApiContext" @@ -25,110 +30,78 @@ const BinFileBrowser: React.FC = ({ controls = false }: const bucket = useMemo(() => buckets.find(b => b.type === "trash"), [buckets]) - const refreshContents = useCallback( - ( - showLoading?: boolean - ) => { - if (!bucket) return - try { - showLoading && setLoadingCurrentPath(true) - filesApiClient.getBucketObjectChildrenList(bucket.id, { path: currentPath }) - .then((newContents) => { - showLoading && setLoadingCurrentPath(false) - setPathContents( - newContents.map((fcr) => parseFileContentResponse(fcr)) - ) - }).catch((error) => { - throw error - }) - } catch (error) { - console.error(error) - showLoading && setLoadingCurrentPath(false) - } - }, - [bucket, currentPath, filesApiClient] + const refreshContents = useCallback((showLoading?: boolean) => { + if (!bucket) return + try { + showLoading && setLoadingCurrentPath(true) + filesApiClient.getBucketObjectChildrenList(bucket.id, { path: currentPath }) + .then((newContents) => { + showLoading && setLoadingCurrentPath(false) + setPathContents( + newContents.map((fcr) => parseFileContentResponse(fcr)) + ) + }).catch((error) => { + throw error + }) + } catch (error) { + console.error(error) + showLoading && setLoadingCurrentPath(false) + } + }, + [bucket, currentPath, filesApiClient] ) useEffect(() => { refreshContents(true) }, [bucket, refreshContents]) - const deleteFile = useCallback(async (cid: string) => { - const itemToDelete = pathContents.find((i) => i.cid === cid) + const deleteItems = useCallback(async (cids: string[]) => { + if (!bucket) return - if (!itemToDelete || !bucket) { - console.error("Bucket not set or no item found to delete") - return - } + const pathsToDelete = getAbsolutePathsFromCids(cids, currentPath, pathContents) + + filesApiClient.removeBucketObject(bucket.id, { paths: pathsToDelete }) + .then(() => { + addToast({ + title: t`Data deleted successfully`, + type: "success", + testId: "deletion-success" + }) + }).catch((error) => { + console.error("Error deleting:", error) + addToast({ + title: t`There was an error deleting your data`, + type: "error" + }) + }).finally(() => { + refreshContents() + refreshBuckets() + }) + }, [addToast, bucket, currentPath, filesApiClient, pathContents, refreshBuckets, refreshContents]) - try { - await filesApiClient.removeBucketObject( - bucket.id, - { paths: [getPathWithFile(currentPath, itemToDelete.name)] } - ) + const recoverItems = useCallback(async (cids: string[], newPath: string) => { + if (!bucket) return - refreshContents() - refreshBuckets() - const message = `${ - itemToDelete.isFolder ? t`Folder` : t`File` - } ${t`deleted successfully`}` + const pathsToRecover = getAbsolutePathsFromCids(cids, currentPath, pathContents) + + filesApiClient.moveBucketObjects( + bucket.id, + { + paths: pathsToRecover, + new_path: pathEndingWithSlash(newPath), + destination: buckets.find(b => b.type === "csf")?.id + } + ).then(() => { addToast({ - title: message, - type: "success", - testId: "permanent-deletion-success" + title: t`Data restored successfully`, + type: "success" }) - return Promise.resolve() - } catch (error) { - const message = `${t`There was an error deleting this`} ${ - itemToDelete.isFolder ? t`folder` : t`file` - }` + }).catch((error) => { + console.error("Error recovering:", error) addToast({ - title: message, + title: t`There was an error restoring your data`, type: "error" }) - return Promise.reject() - } - }, [addToast, bucket, currentPath, pathContents, refreshContents, refreshBuckets, filesApiClient]) - - const deleteItems = useCallback(async (cids: string[]) => { - await Promise.all( - cids.map((cid: string) => - deleteFile(cid) - )) - refreshContents() - }, [deleteFile, refreshContents]) - - const recoverItems = useCallback(async (cids: string[], newPath: string) => { - if (!bucket) return - await Promise.all( - cids.map(async (cid: string) => { - const itemToRestore = pathContents.find((i) => i.cid === cid) - if (!itemToRestore) return - try { - await filesApiClient.moveBucketObjects( - bucket.id, - { - paths: [getPathWithFile(currentPath, itemToRestore.name)], - new_path: getPathWithFile(newPath, itemToRestore.name), - destination: buckets.find(b => b.type === "csf")?.id - } - ) - - const message = `${itemToRestore.isFolder ? t`Folder` : t`File`} ${t`recovered successfully`}` - - addToast({ - title: message, - type: "success" - }) - } catch (error) { - const message = `${t`There was an error recovering this`} ${ - itemToRestore.isFolder ? t`folder` : t`file` - }` - addToast({ - title: message, - type: "error" - }) - } - })).finally(refreshContents) + }).finally(refreshContents) }, [addToast, pathContents, refreshContents, filesApiClient, bucket, buckets, currentPath]) const viewFolder = useCallback((cid: string) => { diff --git a/packages/files-ui/src/Components/Modules/FileBrowsers/CSFFileBrowser.tsx b/packages/files-ui/src/Components/Modules/FileBrowsers/CSFFileBrowser.tsx index 1727cbb873..0627a1663e 100644 --- a/packages/files-ui/src/Components/Modules/FileBrowsers/CSFFileBrowser.tsx +++ b/packages/files-ui/src/Components/Modules/FileBrowsers/CSFFileBrowser.tsx @@ -6,7 +6,9 @@ import { getURISafePathFromArray, getPathWithFile, extractFileBrowserPathFromURL, - getUrlSafePathWithFile + getUrlSafePathWithFile, + getAbsolutePathsFromCids, + pathEndingWithSlash } from "../../../Utils/pathUtils" import { IBulkOperations, IFileBrowserModuleProps, IFilesTableBrowserProps } from "./types" import FilesList from "./views/FilesList" @@ -17,7 +19,6 @@ import { ROUTE_LINKS } from "../../FilesRoutes" import dayjs from "dayjs" import { useFilesApi } from "../../../Contexts/FilesApiContext" import { useUser } from "../../../Contexts/UserContext" -import { useLocalStorage } from "@chainsafe/browser-storage-hooks" import { DISMISSED_SURVEY_KEY } from "../../SurveyBanner" import { FileBrowserContext } from "../../../Contexts/FileBrowserContext" import { parseFileContentResponse } from "../../../Utils/Helpers" @@ -49,10 +50,9 @@ const CSFFileBrowser: React.FC = () => { }).finally(() => showLoading && setLoadingCurrentPath(false)) }, [bucket, filesApiClient, currentPath]) - const { localStorageGet, localStorageSet } = useLocalStorage() - const { profile } = useUser() + const { profile, localStore, setLocalStore } = useUser() - const showSurvey = localStorageGet(DISMISSED_SURVEY_KEY) === "false" + const showSurvey = localStore && localStore[DISMISSED_SURVEY_KEY] === "false" const olderThanOneWeek = useMemo( () => profile?.createdAt @@ -62,11 +62,11 @@ const CSFFileBrowser: React.FC = () => { ) useEffect(() => { - const dismissedFlag = localStorageGet(DISMISSED_SURVEY_KEY) + const dismissedFlag = localStore && localStore[DISMISSED_SURVEY_KEY] if (dismissedFlag === undefined || dismissedFlag === null) { - localStorageSet(DISMISSED_SURVEY_KEY, "false") + setLocalStore({ [DISMISSED_SURVEY_KEY]: "false" }, "update") } - }, [localStorageGet, localStorageSet]) + }, [localStore, setLocalStore]) useEffect(() => { refreshContents(true) @@ -74,43 +74,28 @@ const CSFFileBrowser: React.FC = () => { const moveItemsToBin = useCallback(async (cids: string[], hideToast?: boolean) => { if (!bucket) return - await Promise.all( - cids.map(async (cid: string) => { - const itemToDelete = pathContents.find((i) => i.cid === cid) - if (!itemToDelete) { - console.error("No item found to move to the trash") - return - } - - try { - await filesApiClient.moveBucketObjects(bucket.id, { - paths: [getPathWithFile(currentPath, itemToDelete.name)], - new_path: getPathWithFile("/", itemToDelete.name), - destination: buckets.find(b => b.type === "trash")?.id - }) - if (!hideToast) { - const message = `${ - itemToDelete.isFolder ? t`Folder` : t`File` - } ${t`deleted successfully`}` - const id = addToast({ - title: message, - type: "success", - testId: "deletion-success" - }) - console.log(id) - } - return Promise.resolve() - } catch (error) { - const message = `${t`There was an error deleting this`} ${ - itemToDelete.isFolder ? t`folder` : t`file` - }` - addToast({ - title: message, - type: "error" - }) - return Promise.reject() - }} - )).finally(refreshContents) + + const pathsToDelete = getAbsolutePathsFromCids(cids, currentPath, pathContents) + + filesApiClient.moveBucketObjects(bucket.id, { + paths: pathsToDelete, + new_path: "/", + destination: buckets.find(b => b.type === "trash")?.id + }).then(() => { + if (!hideToast) { + addToast({ + title: t`Data moved to bin successfully`, + type: "success", + testId: "deletion-success" + }) + } + }).catch((error) => { + console.error("Error deleting:", error) + addToast({ + title: t`There was an error deleting your data`, + type: "error" + }) + }).finally(refreshContents) }, [addToast, currentPath, pathContents, refreshContents, filesApiClient, bucket, buckets]) // Rename @@ -127,33 +112,26 @@ const CSFFileBrowser: React.FC = () => { const moveItems = useCallback(async (cids: string[], newPath: string) => { if (!bucket) return - await Promise.all( - cids.map(async (cid: string) => { - const itemToMove = pathContents.find((i) => i.cid === cid) - if (!itemToMove) return - try { - await filesApiClient.moveBucketObjects(bucket.id, { - paths: [getPathWithFile(currentPath, itemToMove.name)], - new_path: getPathWithFile(newPath, itemToMove.name) - }) - const message = `${ - itemToMove.isFolder ? t`Folder` : t`File` - } ${t`moved successfully`}` - - addToast({ - title: message, - type: "success" - }) - } catch (error) { - const message = `${t`There was an error moving this`} ${ - itemToMove.isFolder ? t`folder` : t`file` - }` - addToast({ - title: message, - type: "error" - }) - } - })).finally(refreshContents) + + + const pathsToMove = getAbsolutePathsFromCids(cids, currentPath, pathContents) + + filesApiClient.moveBucketObjects(bucket.id, { + paths: pathsToMove, + new_path: pathEndingWithSlash(newPath) + }).then(() => { + addToast({ + title: t`Data moved successfully`, + type: "success", + testId: "move-success" + }) + }).catch((error) => { + console.error("Error moving:", error) + addToast({ + title: t`There was an error moving your data`, + type: "error" + }) + }).finally(refreshContents) }, [addToast, pathContents, refreshContents, filesApiClient, bucket, currentPath]) const handleDownload = useCallback(async (cid: string) => { @@ -191,8 +169,8 @@ const CSFFileBrowser: React.FC = () => { }, [currentPath, pathContents, redirect]) const bulkOperations: IBulkOperations = useMemo(() => ({ - [CONTENT_TYPES.Directory]: ["download", "move", "delete"], - [CONTENT_TYPES.File]: ["download", "delete", "move"] + [CONTENT_TYPES.Directory]: ["download", "move", "delete", "share"], + [CONTENT_TYPES.File]: ["download", "delete", "move", "share"] }), []) const itemOperations: IFilesTableBrowserProps["itemOperations"] = useMemo(() => ({ @@ -202,7 +180,7 @@ const CSFFileBrowser: React.FC = () => { [CONTENT_TYPES.Pdf]: ["preview"], [CONTENT_TYPES.Text]: ["preview"], [CONTENT_TYPES.File]: ["download", "info", "rename", "move", "delete", "share"], - [CONTENT_TYPES.Directory]: ["download", "rename", "move", "delete"] + [CONTENT_TYPES.Directory]: ["download", "rename", "move", "delete", "share"] }), []) return ( diff --git a/packages/files-ui/src/Components/Modules/FileBrowsers/CreateFolderModal.tsx b/packages/files-ui/src/Components/Modules/FileBrowsers/CreateFolderModal.tsx index d23fcd5d2e..5ab03207c5 100644 --- a/packages/files-ui/src/Components/Modules/FileBrowsers/CreateFolderModal.tsx +++ b/packages/files-ui/src/Components/Modules/FileBrowsers/CreateFolderModal.tsx @@ -99,12 +99,12 @@ const CreateFolderModal = ({ modalOpen, close }: ICreateFolderModalProps) => { setCreatingFolder(false) helpers.resetForm() onCancel() - } catch (errors: any) { + } catch (error: any) { setCreatingFolder(false) - if (errors[0].message.includes("Entry with such name can")) { + if (error?.error?.code === 409) { helpers.setFieldError("name", t`Folder name is already in use`) } else { - helpers.setFieldError("name", errors[0].message) + helpers.setFieldError("name", t`There was an error creating the folder ${error?.message}`) } helpers.setSubmitting(false) } diff --git a/packages/files-ui/src/Components/Modules/FileBrowsers/ShareModal.tsx b/packages/files-ui/src/Components/Modules/FileBrowsers/ShareModal.tsx index 7b7bc01bc5..3c615971bb 100644 --- a/packages/files-ui/src/Components/Modules/FileBrowsers/ShareModal.tsx +++ b/packages/files-ui/src/Components/Modules/FileBrowsers/ShareModal.tsx @@ -180,12 +180,11 @@ const useStyles = makeStyles( ) interface IShareFileProps { - file: FileSystemItem + fileSystemItems: FileSystemItem[] close: () => void - filePath: string } -const ShareModal = ({ close, file, filePath }: IShareFileProps) => { +const ShareModal = ({ close, fileSystemItems }: IShareFileProps) => { const classes = useStyles() const { handleCreateSharedFolder } = useCreateOrEditSharedFolder() const [sharedFolderName, setSharedFolderName] = useState("") @@ -194,7 +193,7 @@ const ShareModal = ({ close, file, filePath }: IShareFileProps) => { const [keepOriginalFile, setKeepOriginalFile] = useState(true) const [destinationBucket, setDestinationBucket] = useState() const { buckets, transferFileBetweenBuckets } = useFiles() - const { bucket } = useFileBrowser() + const { bucket, currentPath } = useFileBrowser() const { profile } = useUser() const [nameError, setNameError] = useState("") const inSharedBucket = useMemo(() => bucket?.type === "share", [bucket]) @@ -284,13 +283,11 @@ const ShareModal = ({ close, file, filePath }: IShareFileProps) => { return } - transferFileBetweenBuckets(bucket.id, file, filePath, bucketToUpload, keepOriginalFile) + transferFileBetweenBuckets(bucket, fileSystemItems, currentPath, bucketToUpload, keepOriginalFile) close() }, [ bucket, destinationBucket, - file, - filePath, handleCreateSharedFolder, isUsingCurrentBucket, sharedFolderName, @@ -298,7 +295,9 @@ const ShareModal = ({ close, file, filePath }: IShareFileProps) => { sharedFolderWriters, keepOriginalFile, close, - transferFileBetweenBuckets + transferFileBetweenBuckets, + currentPath, + fileSystemItems ]) return ( @@ -428,7 +427,7 @@ const ShareModal = ({ close, file, filePath }: IShareFileProps) => { setKeepOriginalFile(!keepOriginalFile)} - label={t`Keep original file`} + label={t`Keep original files`} />
)} diff --git a/packages/files-ui/src/Components/Modules/FileBrowsers/SharedFileBrowser.tsx b/packages/files-ui/src/Components/Modules/FileBrowsers/SharedFileBrowser.tsx index f061203da6..918c55989d 100644 --- a/packages/files-ui/src/Components/Modules/FileBrowsers/SharedFileBrowser.tsx +++ b/packages/files-ui/src/Components/Modules/FileBrowsers/SharedFileBrowser.tsx @@ -5,7 +5,9 @@ import { getURISafePathFromArray, getPathWithFile, extractSharedFileBrowserPathFromURL, - getUrlSafePathWithFile + getUrlSafePathWithFile, + getAbsolutePathsFromCids, + pathEndingWithSlash } from "../../../Utils/pathUtils" import { IBulkOperations, IFilesTableBrowserProps } from "./types" import { CONTENT_TYPES } from "../../../Utils/Constants" @@ -20,7 +22,7 @@ import DragAndDrop from "../../../Contexts/DnDContext" import FilesList from "./views/FilesList" const SharedFileBrowser = () => { - const { downloadFile, uploadFiles, buckets, refreshBuckets, getStorageSummary } = useFiles() + const { downloadFile, uploadFiles, buckets, getStorageSummary, refreshBuckets } = useFiles() const { filesApiClient } = useFilesApi() const { addToast } = useToasts() const [loadingCurrentPath, setLoadingCurrentPath] = useState(false) @@ -94,48 +96,29 @@ const SharedFileBrowser = () => { refreshContents(true) }, [bucket, refreshContents]) - const deleteFile = useCallback(async (cid: string) => { - const itemToDelete = pathContents.find((i) => i.cid === cid) + const deleteItems = useCallback(async (cids: string[]) => { + if (!bucket) return - if (!itemToDelete || !bucket) { - console.error("Bucket not set or no item found to delete") - return - } + const pathsToDelete = getAbsolutePathsFromCids(cids, currentPath, pathContents) - try { - await filesApiClient.removeBucketObject( - bucket.id, - { paths: [getPathWithFile(currentPath, itemToDelete.name)] } - ) - - refreshContents(false) - refreshBuckets(false) - const message = `${ - itemToDelete.isFolder ? t`Folder` : t`File` - } ${t`deleted successfully`}` - addToast({ - title: message, - type: "success" - }) - return Promise.resolve() - } catch (error) { - const message = `${t`There was an error deleting this`} ${ - itemToDelete.isFolder ? t`folder` : t`file` - }` - addToast({ - title: message, - type: "error" + filesApiClient.removeBucketObject(bucket.id, { paths: pathsToDelete }) + .then(() => { + addToast({ + title: t`Data deleted successfully`, + type: "success", + testId: "deletion-success" + }) + }).catch((error) => { + console.error("Error deleting:", error) + addToast({ + title: t`There was an error deleting your data`, + type: "error" + }) + }).finally(() => { + refreshContents() + refreshBuckets() }) - return Promise.reject() - } - }, [addToast, bucket, currentPath, pathContents, refreshContents, refreshBuckets, filesApiClient]) - - const deleteItems = useCallback(async (cids: string[]) => { - await Promise.all( - cids.map((cid: string) => - deleteFile(cid) - )) - }, [deleteFile]) + }, [addToast, bucket, currentPath, filesApiClient, pathContents, refreshBuckets, refreshContents]) // Rename const renameItem = useCallback(async (cid: string, newName: string) => { @@ -150,16 +133,25 @@ const SharedFileBrowser = () => { const moveItems = useCallback(async (cids: string[], newPath: string) => { if (!bucket) return - await Promise.all( - cids.map(async (cid: string) => { - const itemToMove = pathContents.find(i => i.cid === cid) - if (!bucket || !itemToMove) return - await filesApiClient.moveBucketObjects(bucket.id, { - paths: [getPathWithFile(currentPath, itemToMove.name)], - new_path: getPathWithFile(newPath, itemToMove.name) - }) - })).finally(refreshContents) - }, [refreshContents, filesApiClient, bucket, currentPath, pathContents]) + + const pathsToMove = getAbsolutePathsFromCids(cids, currentPath, pathContents) + + filesApiClient.moveBucketObjects(bucket.id, { + paths: pathsToMove, + new_path: pathEndingWithSlash(newPath) + }).then(() => { + addToast({ + title: t`Data moved successfully`, + type: "success" + }) + }).catch((error) => { + console.error("Error recovering:", error) + addToast({ + title: t`There was an error restoring your data`, + type: "error" + }) + }).finally(refreshContents) + }, [refreshContents, filesApiClient, bucket, currentPath, pathContents, addToast]) const handleDownload = useCallback(async (cid: string) => { const itemToDownload = pathContents.find(item => item.cid === cid) @@ -198,7 +190,7 @@ const SharedFileBrowser = () => { }, [addToast, uploadFiles, bucket, refreshContents]) const bulkOperations: IBulkOperations = useMemo(() => ({ - [CONTENT_TYPES.Directory]: ["download", "move", "delete"], + [CONTENT_TYPES.Directory]: ["download", "move", "delete", "share"], [CONTENT_TYPES.File]: ["download", "delete", "move", "share"] }), []) @@ -212,7 +204,7 @@ const SharedFileBrowser = () => { [CONTENT_TYPES.Pdf]: ["preview"], [CONTENT_TYPES.Text]: ["preview"], [CONTENT_TYPES.File]: ["download", "info", "rename", "move", "delete", "share"], - [CONTENT_TYPES.Directory]: ["rename", "move", "delete"] + [CONTENT_TYPES.Directory]: ["rename", "move", "delete", "share"] } case "writer": return { @@ -222,7 +214,7 @@ const SharedFileBrowser = () => { [CONTENT_TYPES.Pdf]: ["preview"], [CONTENT_TYPES.Text]: ["preview"], [CONTENT_TYPES.File]: ["download", "info", "rename", "move", "delete", "report", "share"], - [CONTENT_TYPES.Directory]: ["rename", "move", "delete"] + [CONTENT_TYPES.Directory]: ["rename", "move", "delete", "share"] } // case "reader": default: diff --git a/packages/files-ui/src/Components/Modules/FileBrowsers/UploadFileModal.tsx b/packages/files-ui/src/Components/Modules/FileBrowsers/UploadFileModal.tsx index d2a0615753..e40c8fd2cd 100644 --- a/packages/files-ui/src/Components/Modules/FileBrowsers/UploadFileModal.tsx +++ b/packages/files-ui/src/Components/Modules/FileBrowsers/UploadFileModal.tsx @@ -102,12 +102,8 @@ const UploadFileModule = ({ modalOpen, close }: IUploadFileModuleProps) => { }) refreshContents && refreshContents() helpers.resetForm() - } catch (errors: any) { - if (errors[0].message.includes("conflict with existing")) { - helpers.setFieldError("files", "File/Folder exists") - } else { - helpers.setFieldError("files", errors[0].message) - } + } catch (error: any) { + console.error(error) } helpers.setSubmitting(false) }, [close, currentPath, uploadFiles, refreshContents, bucket]) diff --git a/packages/files-ui/src/Components/Modules/FileBrowsers/hooks/useSharingExplainerModalFlag.tsx b/packages/files-ui/src/Components/Modules/FileBrowsers/hooks/useSharingExplainerModalFlag.tsx index b9282d79d2..99d4ea335f 100644 --- a/packages/files-ui/src/Components/Modules/FileBrowsers/hooks/useSharingExplainerModalFlag.tsx +++ b/packages/files-ui/src/Components/Modules/FileBrowsers/hooks/useSharingExplainerModalFlag.tsx @@ -1,28 +1,28 @@ -import { useLocalStorage } from "@chainsafe/browser-storage-hooks" import { useCallback } from "react" import { useEffect, useState } from "react" +import { useUser } from "../../../../Contexts/UserContext" export const DISMISSED_SHARING_EXPLAINER_KEY = "csf.dismissedSharingExplainer" export const useSharingExplainerModalFlag = () => { - const { localStorageGet, localStorageSet } = useLocalStorage() + const { localStore, setLocalStore } = useUser() const [hasSeenSharingExplainerModal, setHasSeenSharingExplainerModal] = useState(false) - const dismissedFlag = localStorageGet(DISMISSED_SHARING_EXPLAINER_KEY) + const dismissedFlag = localStore ? localStore[DISMISSED_SHARING_EXPLAINER_KEY] : null useEffect(() => { if (dismissedFlag === "false"){ setHasSeenSharingExplainerModal(true) } else if (dismissedFlag === null) { // the dismiss flag was never set - localStorageSet(DISMISSED_SHARING_EXPLAINER_KEY, "false") + setLocalStore({ [DISMISSED_SHARING_EXPLAINER_KEY]: "false" }, "update") setHasSeenSharingExplainerModal(true) } - }, [dismissedFlag, localStorageSet]) + }, [dismissedFlag, setLocalStore]) const hideModal = useCallback(() => { - localStorageSet(DISMISSED_SHARING_EXPLAINER_KEY, "true") + setLocalStore({ [DISMISSED_SHARING_EXPLAINER_KEY]: "true" }, "update") setHasSeenSharingExplainerModal(false) - }, [localStorageSet]) + }, [setLocalStore]) return { hasSeenSharingExplainerModal, hideModal } } \ No newline at end of file diff --git a/packages/files-ui/src/Components/Modules/FileBrowsers/views/FileSystemItem/FileSystemItem.tsx b/packages/files-ui/src/Components/Modules/FileBrowsers/views/FileSystemItem/FileSystemItem.tsx index 79c6937151..0dabb8a43a 100644 --- a/packages/files-ui/src/Components/Modules/FileBrowsers/views/FileSystemItem/FileSystemItem.tsx +++ b/packages/files-ui/src/Components/Modules/FileBrowsers/views/FileSystemItem/FileSystemItem.tsx @@ -122,7 +122,7 @@ interface IFileSystemItemProps { browserView: BrowserView reportFile?: (path: string) => void showFileInfo?: (path: string) => void - share?: (path: string, fileIndex: number) => void + handleShare?: (file: FileSystemItemType) => void showPreview?: (fileIndex: number) => void } @@ -145,7 +145,7 @@ const FileSystemItem = ({ resetSelectedFiles, reportFile, showFileInfo, - share, + handleShare, showPreview }: IFileSystemItemProps) => { const { bucket, downloadFile, currentPath, handleUploadOnDrop, moveItems } = useFileBrowser() @@ -247,7 +247,7 @@ const FileSystemItem = ({ ), - onClick: () => share && share(filePath, files?.indexOf(file)) + onClick: () => handleShare && handleShare(file) }, info: { contents: ( @@ -316,9 +316,8 @@ const FileSystemItem = ({ currentPath, downloadFile, moveFile, - share, + handleShare, filePath, - files, showFileInfo, recoverFile, onFilePreview, diff --git a/packages/files-ui/src/Components/Modules/FileBrowsers/views/FileSystemItem/SharedFolderRow.tsx b/packages/files-ui/src/Components/Modules/FileBrowsers/views/FileSystemItem/SharedFolderRow.tsx index bb407017c7..6a078ed736 100644 --- a/packages/files-ui/src/Components/Modules/FileBrowsers/views/FileSystemItem/SharedFolderRow.tsx +++ b/packages/files-ui/src/Components/Modules/FileBrowsers/views/FileSystemItem/SharedFolderRow.tsx @@ -24,6 +24,7 @@ import { BucketKeyPermission } from "../../../../../Contexts/FilesContext" import UserBubble from "../../../../Elements/UserBubble" import { nameValidator } from "../../../../../Utils/validationSchema" import Menu from "../../../../../UI-components/Menu" +import { getUserDisplayName } from "../../../../../Utils/getUserDisplayName" const useStyles = makeStyles(({ breakpoints, constants, palette }: CSFTheme) => { @@ -275,7 +276,7 @@ const SharedFolderRow = ({ bucket, handleRename, openSharedFolder, handleDeleteS {isOwner ? t`me` - : } + : } } { setIsDeleteModalOpen(true) }, []) + const handleOpenShareDialog = useCallback((e: React.MouseEvent) => { + e.preventDefault() + e.stopPropagation() + setIsShareModalOpen(true) + }, []) + const mobileMenuItems = useMemo(() => [ { contents: ( @@ -642,13 +648,12 @@ const FilesList = ({ isShared = false }: Props) => { ], [classes.menuIcon]) - const onShare = useCallback((fileInfoPath: string, fileIndex: number) => { + const onShare = useCallback((fileSystemItem: FileSystemItemType) => { if(hasSeenSharingExplainerModal) { setClickedShare(true) } - setFilePath(fileInfoPath) - setFileIndex(fileIndex) + setSelectedItems([fileSystemItem]) setIsShareModalOpen(true) }, [hasSeenSharingExplainerModal]) @@ -817,6 +822,15 @@ const FilesList = ({ isShared = false }: Props) => { Delete selected )} + {validBulkOps.includes("share") && ( + + )} )} @@ -954,7 +968,7 @@ const FilesList = ({ isShared = false }: Props) => { setFileIndex(fileIndex) setIsPreviewOpen(true) }} - share={onShare} + handleShare={onShare} /> ))} @@ -1007,7 +1021,7 @@ const FilesList = ({ isShared = false }: Props) => { setFilePath(fileInfoPath) setIsFileInfoModalOpen(true) }} - share={onShare} + handleShare={onShare} showPreview={(fileIndex: number) => { setFileIndex(fileIndex) setIsPreviewOpen(true) @@ -1093,14 +1107,13 @@ const FilesList = ({ isShared = false }: Props) => { }} /> } - { !showExplainerBeforeShare && isShareModalOpen && filePath && fileIndex !== undefined && + { !showExplainerBeforeShare && isShareModalOpen && selectedItems.length && { setIsShareModalOpen(false) setFilePath(undefined) }} - filePath={currentPath} + fileSystemItems={selectedItems} /> } { setLoginMode(loginType) try { await login(loginType) - } catch (error) { + } catch (error: any) { let errorMessage = t`There was an error authenticating` - console.log(error) - if (Array.isArray(error) && error[0]) { - if ( - error[0].type === "signature" && - error[0].message === "Invalid signature" - ) { - errorMessage = t`Failed to validate signature. + // Invalid signature, or contract wallet not deployed + if (error?.error?.code === 403 && error?.error?.message?.includes("Invalid signature")) { + errorMessage = t`Failed to validate signature. If you are using a contract wallet, please make sure you have activated your wallet.` - } } - // WalletConnect be sassy - if ((error instanceof Error && error.message === "Just nope") || ((error as any).code === 4001)) { + // User rejected the signature request (WalletConnect be sassy) + if (error?.message === "Just nope" || error?.code === 4001) { errorMessage = t`Failed to get signature` } - if (error instanceof Error && error?.message === "user closed popup") { + // DirectAuth popup was closed + if (error?.message === "user closed popup") { errorMessage = t`The authentication popup was closed` } diff --git a/packages/files-ui/src/Components/SharingExplainerModal.tsx b/packages/files-ui/src/Components/SharingExplainerModal.tsx index 05e9544503..4061e965dd 100644 --- a/packages/files-ui/src/Components/SharingExplainerModal.tsx +++ b/packages/files-ui/src/Components/SharingExplainerModal.tsx @@ -1,4 +1,3 @@ -import { useLocalStorage } from "@chainsafe/browser-storage-hooks" import { Button, Link, Typography } from "@chainsafe/common-components" import { createStyles, makeStyles } from "@chainsafe/common-theme" import { t, Trans } from "@lingui/macro" @@ -10,6 +9,7 @@ import step1Image from "../Media/sharingExplainer/step1.png" import step2Image from "../Media/sharingExplainer/step2.png" import step3Image from "../Media/sharingExplainer/step3.png" import { DISMISSED_SHARING_EXPLAINER_KEY } from "./Modules/FileBrowsers/hooks/useSharingExplainerModalFlag" +import { useUser } from "../Contexts/UserContext" const useStyles = makeStyles( ({ palette, constants }: CSFTheme) => { @@ -76,7 +76,7 @@ const STEP_NUMBER = 3 const SharingExplainerModal = ({ showModal, onHide }: Props) => { const classes = useStyles() - const { localStorageSet } = useLocalStorage() + const { setLocalStore } = useUser() const [step, setStep] = useState(1) const Slides = useCallback(() => { switch (step) { @@ -133,7 +133,7 @@ const SharingExplainerModal = ({ showModal, onHide }: Props) => { } else { switch (next) { case 3: - localStorageSet(DISMISSED_SHARING_EXPLAINER_KEY, "true") + setLocalStore({ [DISMISSED_SHARING_EXPLAINER_KEY]: "true" }, "update") setStep(3) break case STEP_NUMBER + 1: @@ -143,7 +143,7 @@ const SharingExplainerModal = ({ showModal, onHide }: Props) => { break } } - }, [localStorageSet, onHide]) + }, [setLocalStore, onHide]) return ( { const classes = useStyles() - const { localStorageSet } = useLocalStorage() + const { setLocalStore } = useUser() const onClose = useCallback(() => { onHide() - localStorageSet(DISMISSED_SURVEY_KEY, "true") - }, [localStorageSet, onHide]) + setLocalStore({ [DISMISSED_SURVEY_KEY]: "true" }, "update") + }, [setLocalStore, onHide]) const onOpen = useCallback(() => { onClose() diff --git a/packages/files-ui/src/Contexts/FilesContext.tsx b/packages/files-ui/src/Contexts/FilesContext.tsx index 8aeb8158a2..dc8f2e3aec 100644 --- a/packages/files-ui/src/Contexts/FilesContext.tsx +++ b/packages/files-ui/src/Contexts/FilesContext.tsx @@ -80,9 +80,9 @@ type FilesContext = { readers?: UpdateSharedFolderUser[] ) => Promise transferFileBetweenBuckets: ( - sourceBucketId: string, - sourceFile: FileSystemItem, - path: string, + sourceBucket: BucketKeyPermission, + sourceItems: FileSystemItem[], + currentPath: string, destinationBucket: BucketKeyPermission, deleteFromSource?: boolean ) => Promise @@ -380,8 +380,7 @@ const FilesProvider = ({ children }: FilesContextProps) => { type: "success", progress: 0, onProgressCancel: cancelSource.cancel, - isClosable: false, - testId: "upload-status" + isClosable: false } const toastId = addToast(toastParams) @@ -411,20 +410,20 @@ const FilesProvider = ({ children }: FilesContextProps) => { title: "Upload complete", progress: undefined, onProgressCancel: undefined, - isClosable: true + isClosable: true, + testId: "upload-complete" }, true) return Promise.resolve() } catch (error: any) { setUploadsInProgress(false) // setting error let errorMessage = t`Something went wrong. We couldn't upload your file` - // uploads cancelled through button if (axios.isCancel(error)) { errorMessage = t`Uploads cancelled` } // we will need a method to parse server errors - if (Array.isArray(error) && error[0].message.includes("conflict")) { + if (error?.error?.code === 409) { errorMessage = t`A file with the same name already exists` } updateToast(toastId, { @@ -663,7 +662,7 @@ const FilesProvider = ({ children }: FilesContextProps) => { return Promise.resolve() } catch (error: any) { console.error(error) - let errorMessage = `${t`An error occurred: `} ${typeof(error) === "string" ? error : error.length ? error[0].message : ""}` + let errorMessage = `${t`An error occurred: `} ${typeof(error) === "string" ? error : error.error.message ? error.error.message : ""}` if (axios.isCancel(error)) { errorMessage = t`Downloads cancelled` } @@ -748,98 +747,130 @@ const FilesProvider = ({ children }: FilesContextProps) => { }, [publicKey, getUsersWithEncryptionKey, filesApiClient, refreshBuckets]) const transferFileBetweenBuckets = useCallback(async ( - sourceBucketId: string, - sourceFile: FileSystemItem, - path: string, + sourceBucket: BucketKeyPermission, + sourceItems: FileSystemItem[], + currentPath: string, destinationBucket: BucketKeyPermission, keepOriginal = true ) => { - const UPLOAD_PATH = "/" + getFileList(sourceItems, currentPath, sourceBucket.id).then(async (allItems) => { + setTransfersInProgress(true) + const inSharedBucket = sourceBucket.type === "share" + const cancelSource = axios.CancelToken.source() + const cancelToken = cancelSource.token + + const totalFileSize = allItems.reduce((sum, item) => sum + item.size, 0) + const totalFileNumber = allItems.length + + if (!totalFileNumber) { + addToast({ + title: inSharedBucket + ? t`No files to copy` + : t`No files to share`, + type: "error" + }) + return + } - const cancelSource = axios.CancelToken.source() - const cancelToken = cancelSource.token + const toastParams: ToastParams = { + title: inSharedBucket + ? t`Copying files` + : t`Sharing files`, + type: "success", + progress: 0, + onProgressCancel: cancelSource.cancel, + isClosable: false + } + const toastId = addToast(toastParams) + let successCount = 0 + + try { + await allItems.reduce(async (totalProgress: Promise, item, i) => { + const previousProgress = await totalProgress + const fileProgress = `${i + 1}/${totalFileNumber}` + try { + const file = await getFileContent(sourceBucket.id, { + cid: item.cid, + file: item, + path: getPathWithFile(item.path, item.name), + cancelToken, + onDownloadProgress: async (progressEvent) => { + const currentProgress = Math.ceil((((2 * previousProgress) + progressEvent.loaded) * 50) / totalFileSize) + updateToast(toastId, { + ...toastParams, + title: t`${inSharedBucket ? "Copying" : "Sharing"} ${fileProgress} - ${item.name}`, + progress: currentProgress + }) + } + }) - const toastParams: ToastParams = { - title: t`Sharing your file (Downloading)`, - type: "success", - progress: 0, - onProgressCancel: cancelSource.cancel, - isClosable: false - } - const toastId = addToast(toastParams) - setTransfersInProgress(true) + if(file) { + await encryptAndUploadFiles( + destinationBucket, + [new File([file], item.name, { type: item.content_type })], + getRelativePath(item.path, currentPath), + async (progressEvent) => { + const currentProgress = Math.ceil((((2 * previousProgress) + progressEvent.loaded + item.size) * 50) / totalFileSize) + updateToast(toastId, { + title: t`${inSharedBucket ? "Copying" : "Sharing"} ${fileProgress} - ${item.name}`, + type: "success", + progress: currentProgress + }) + }, + cancelToken + ) + } + + if (!keepOriginal) { + await filesApiClient.removeBucketObject(sourceBucket.id, { paths: [getPathWithFile(item.path, item.name)] }) + } + successCount++ + return previousProgress + item.size + } catch (error) { + console.error(error) + return previousProgress + item.size + } + }, Promise.resolve(0)) - getFileContent(sourceBucketId, { - cid: sourceFile.cid, - file: sourceFile, - path: getPathWithFile(path, sourceFile.name), - cancelToken, - onDownloadProgress: (progressEvent) => { - updateToast(toastId, { - ...toastParams, - progress: Math.ceil( - (progressEvent.loaded / sourceFile.size) * 50 - ) - }) - } - }).then(async (fileContent) => { - if (!fileContent) { updateToast(toastId, { - title: t`An error occurred while downloading the file`, - type: "error", - progress: undefined, - onProgressCancel: undefined, + title: successCount === totalFileNumber + ? t`${inSharedBucket ? "Copying" : "Sharing"} complete` + : successCount + ? t`${successCount} files transferred successfully, ${totalFileNumber - successCount} failed` + : t`${inSharedBucket ? "Copying" : "Sharing"} failed`, + type: "success", + progress: undefined, isClosable: true }, true) setTransfersInProgress(false) - return - } + refreshBuckets() - await encryptAndUploadFiles( - destinationBucket, - [new File([fileContent], sourceFile.name, { type: sourceFile.content_type })], - UPLOAD_PATH, - (progressEvent) => { - updateToast(toastId, { - title: t`Encrypting & uploading`, - type: "success", - progress: Math.ceil( - 50 + (progressEvent.loaded / sourceFile.size) * 50 - ) - }) - }, - cancelToken - ) - - if (!keepOriginal) { - await filesApiClient.removeBucketObject(sourceBucketId, { paths: [getPathWithFile(path, sourceFile.name)] }) + } catch (error) { + console.error(error) + setTransfersInProgress(false) + let errorMessage = successCount + ? t`${successCount} files transferred successfully, ${totalFileNumber - successCount} failed` + : t`${inSharedBucket ? "Copying" : "Sharing"} failed` + if (axios.isCancel(error)) { + errorMessage = successCount + ? t`${ + inSharedBucket ? "Copying" : "Sharing" + } cancelled - ${successCount} files ${inSharedBucket ? "copied" : "shared"} successfully` + : t`${inSharedBucket ? "Copying" : "Sharing"} cancelled` + } + updateToast(toastId, { + title: errorMessage, + type: "error", + progress: undefined, + isClosable: true + }, true) } - updateToast(toastId, { - title: t`Transfer complete`, - type: "success", - progress: undefined, - isClosable: true - }, true) - setTransfersInProgress(false) - return Promise.resolve() }).catch((error) => { console.error(error) - let errorMessage = `${t`An error occurred: `} ${typeof(error) === "string" ? error : error.length ? error[0].message : ""}` - if (axios.isCancel(error)) { - errorMessage = t`Sharing cancelled` - } - updateToast(toastId, { - title: errorMessage, - type: "error", - progress: undefined, - onProgressCancel: undefined, - isClosable: true - }, true) - setTransfersInProgress(false) }).finally(() => { refreshBuckets() }) - }, [getFileContent, encryptAndUploadFiles, filesApiClient, refreshBuckets, addToast, updateToast]) + }, [getFileContent, encryptAndUploadFiles, filesApiClient, refreshBuckets, addToast, updateToast, getFileList]) return ( void refreshProfile(): Promise updateProfile: ( firstName: string, @@ -34,10 +41,26 @@ interface IUserContext { const UserContext = React.createContext(undefined) + const UserProvider = ({ children }: UserContextProps) => { const { filesApiClient, isLoggedIn } = useFilesApi() const [profile, setProfile] = useState(undefined) + const [localStore, _setLocalStore] = useState() + + const setLocalStore = useCallback((newData: ILocalStore, method: "update" | "overwrite" = "update") => { + switch (method) { + case "update": + _setLocalStore({ + ...localStore, + ...newData + }) + break + case "overwrite": + _setLocalStore(newData) + break + } + }, [localStore]) const refreshProfile = useCallback(async () => { try { @@ -59,6 +82,31 @@ const UserProvider = ({ children }: UserContextProps) => { } }, [filesApiClient]) + useEffect(() => { + const manageAsync = async () => { + if (!localStore) { + // Fetch + try { + const fetched = await filesApiClient.getUserLocalStore() + if (!fetched) { + _setLocalStore({}) + } else { + _setLocalStore(fetched) + } + } catch(error) { + console.error(error) + _setLocalStore({}) + } + } else { + // Store + await filesApiClient.updateUserLocalStore(localStore) + } + } + if (isLoggedIn) { + manageAsync() + } + }, [isLoggedIn, localStore, filesApiClient]) + useEffect(() => { if (isLoggedIn) { refreshProfile() @@ -86,10 +134,11 @@ const UserProvider = ({ children }: UserContextProps) => { }) return Promise.resolve() } catch (error: any) { + console.error(error) return Promise.reject( - Array.isArray(error) && error[0] - ? error[0].message - : "There was an error updating profile." + Array.isArray(error.error.details) + ? error.error.details.map((e: Details) => e.message).join(",") + : t`There was an error when setting username.` ) } } @@ -113,9 +162,10 @@ const UserProvider = ({ children }: UserContextProps) => { }) return Promise.resolve() } catch (error: any) { + console.error(error) return Promise.reject( - Array.isArray(error) && error[0] - ? error[0].message + Array.isArray(error.error.details) + ? error.error.details.map((e: Details) => e.message).join(",") : t`There was an error when setting username.` ) } @@ -132,7 +182,10 @@ const UserProvider = ({ children }: UserContextProps) => { } } - const removeUser = useCallback(() => setProfile(undefined), []) + const removeUser = useCallback(() => { + setProfile(undefined) + _setLocalStore(undefined) + }, []) const getProfileTitle = () => { if (profile?.publicAddress) { @@ -149,6 +202,8 @@ const UserProvider = ({ children }: UserContextProps) => { return ( { return `${urlSafePath}/${encodeURIComponent(fileName)}` } + +export const getAbsolutePathsFromCids = (cids: string[], currentPath: string, pathContents: FileSystemItem[]) => { + return cids.map((cid: string) => { + const item = pathContents.find((i) => i.cid === cid) + if (!item) { + return undefined + } + return getPathWithFile(currentPath, item.name) + }).filter((item): item is string => !!item) +} + +export const pathEndingWithSlash = (path: string) => { + const lastChar = path.substr(-1) + return lastChar === "/" + ? path + : `${path}/` +} \ No newline at end of file diff --git a/packages/files-ui/src/locales/de/messages.po b/packages/files-ui/src/locales/de/messages.po index 9a35b60490..c03ea80731 100644 --- a/packages/files-ui/src/locales/de/messages.po +++ b/packages/files-ui/src/locales/de/messages.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-20 00:28+0200\n" -"PO-Revision-Date: 2021-09-22 21:38+0000\n" +"PO-Revision-Date: 2021-09-29 19:36+0000\n" "Last-Translator: J. Lavoie \n" "Language-Team: German \n" "Language: de\n" @@ -17,7 +17,7 @@ msgid "A backup secret phrase will be generated and used for your account.<0/>We msgstr "Es wird ein Sicherungsgeheimsatz generiert und für Ihr Konto verwendet.<0/>Wir speichern ihn nicht und <1>er kann nur einmal angezeigt werden. Speichern Sie ihn an einem sicheren Ort!" msgid "A better sharing experience is coming soon." -msgstr "" +msgstr "Ein besseres Teilen-Erlebnis ist in Vorbereitung." msgid "A file with the same name already exists" msgstr "Es existiert bereits eine Datei mit demselben Namen" @@ -35,7 +35,7 @@ msgid "Add at least one more authentication method to protect your account. You msgstr "Fügen Sie mindestens eine weitere Authentifizierungsmethode hinzu, um Ihr Konto zu schützen. Sie bräuchten nur zwei, um sich von jedem Gerät aus bei Files anzumelden." msgid "Add by sharing address, username or wallet address" -msgstr "" +msgstr "Durch Freigabe der Adresse, des Benutzernamens oder der Brieftaschenadresse hinzufügen" msgid "Add more files" msgstr "Weitere Dateien hinzufügen" @@ -43,9 +43,6 @@ msgstr "Weitere Dateien hinzufügen" msgid "Add viewers and editors by username, sharing id or Ethereum address." msgstr "" -msgid "An error occurred while downloading the file" -msgstr "Beim Herunterladen der Datei ist ein Fehler aufgetreten" - msgid "An error occurred:" msgstr "Es ist ein Fehler aufgetreten:" @@ -142,11 +139,14 @@ msgstr "" msgid "Copy to" msgstr "" +msgid "Copying files" +msgstr "" + msgid "Create" msgstr "Erstellen" msgid "Create Folder" -msgstr "Ordner erstellen" +msgstr "" msgid "Create Shared Folder" msgstr "" @@ -166,6 +166,18 @@ msgstr "" msgid "Dark Theme" msgstr "Dunkles Farbschema" +msgid "Data deleted successfully" +msgstr "" + +msgid "Data moved successfully" +msgstr "" + +msgid "Data moved to bin successfully" +msgstr "" + +msgid "Data restored successfully" +msgstr "" + msgid "Date uploaded" msgstr "Hochgeladen am" @@ -220,9 +232,6 @@ msgstr "Zum Hochladen von Dateien ablegen" msgid "Email is required" msgstr "E-Mail ist erforderlich" -msgid "Encrypting & uploading" -msgstr "" - msgid "Enter backup secret phrase:" msgstr "Geben Sie den Sicherungsgeheimsatz ein:" @@ -250,9 +259,6 @@ msgid "" "sure you have activated your wallet." msgstr "" -msgid "File" -msgstr "Datei" - msgid "File Info" msgstr "Dateiinfos" @@ -274,9 +280,6 @@ msgstr "Dateifreigabeschlüssel" msgid "First name" msgstr "Vorname" -msgid "Folder" -msgstr "Ordner" - msgid "Folder name is already in use" msgstr "" @@ -340,7 +343,7 @@ msgstr "Infos" msgid "I’m done saving my backup secret phrase" msgstr "Ich bin fertig mit dem Speichern meines Sixherungsgeheimsatzes" -msgid "Keep original file" +msgid "Keep original files" msgstr "" msgid "Language" @@ -418,6 +421,12 @@ msgstr "Schön, Sie wiederzusehen!" msgid "No file to download." msgstr "" +msgid "No files to copy" +msgstr "" + +msgid "No files to share" +msgstr "" + msgid "No files to show" msgstr "Keine Dateien zum Anzeigen" @@ -437,7 +446,7 @@ msgid "Number of copies (Replication Factor)" msgstr "Anzahl der Kopien (Replikationsfaktor)" msgid "OK" -msgstr "OK" +msgstr "" msgid "One sec, getting files ready…" msgstr "Eine Sekunde, die Dateien werden vorbereitet …" @@ -530,16 +539,19 @@ msgid "Rename" msgstr "Umbenennen" msgid "Rename file" -msgstr "" +msgstr "Datei umbenennen" msgid "Rename folder" -msgstr "" +msgstr "Ordner umbenennen" msgid "Report" -msgstr "" +msgstr "Melden" msgid "Report a File" -msgstr "" +msgstr "Datei melden" + +msgid "Report a bug" +msgstr "Fehler melden" msgid "Report a bug" msgstr "" @@ -613,6 +625,9 @@ msgstr "" msgid "Share file" msgstr "" +msgid "Share selected" +msgstr "" + msgid "Shared" msgstr "Geteilt" @@ -625,10 +640,7 @@ msgstr "" msgid "Shared with" msgstr "" -msgid "Sharing cancelled" -msgstr "" - -msgid "Sharing your file (Downloading)" +msgid "Sharing files" msgstr "" msgid "Sign Out" @@ -706,8 +718,11 @@ msgstr "Es gab einen Fehler bei der Authentifizierung" msgid "There was an error connecting your wallet" msgstr "" -msgid "There was an error deleting this" -msgstr "Es gab einen Fehler beim Löschen dieses" +msgid "There was an error creating the folder {0}" +msgstr "" + +msgid "There was an error deleting your data" +msgstr "" msgid "There was an error getting search results" msgstr "Es gab einen Fehler beim Abrufen der Suchergebnisse" @@ -715,11 +730,11 @@ msgstr "Es gab einen Fehler beim Abrufen der Suchergebnisse" msgid "There was an error getting the preview." msgstr "Es gab einen Fehler beim Abrufen der Vorschau." -msgid "There was an error moving this" -msgstr "Es gab einen Fehler beim Verschieben dieses" +msgid "There was an error moving your data" +msgstr "" -msgid "There was an error recovering this" -msgstr "Es gab einen Fehler bei der Wiederherstellung dieses" +msgid "There was an error restoring your data" +msgstr "" msgid "There was an error when setting username." msgstr "" @@ -736,9 +751,6 @@ msgstr "" msgid "This website uses cookies that help the website function and track interactions for analytics purposes. You have the right to decline our use of cookies. For us to provide a customizable user experience to you, please click on the Accept button below.<0>Learn more" msgstr "" -msgid "Transfer complete" -msgstr "" - msgid "Try again" msgstr "Erneut versuchen" @@ -838,27 +850,12 @@ msgstr "" msgid "Your recovery key can be used to restore your account in place of your backup secret phrase." msgstr "Ihr Wiederherstellungsschlüssel kann zur Wiederherstellung Ihres Kontos anstelle Ihres Sicherungsgeheimsatz verwendet werden." -msgid "deleted successfully" -msgstr "erfolgreich gelöscht" - -msgid "file" -msgstr "Datei" - -msgid "folder" -msgstr "Ordner" - msgid "me" msgstr "ich" -msgid "moved successfully" -msgstr "erfolgreich verschoben" - msgid "on" msgstr "am" -msgid "recovered successfully" -msgstr "erfolgreich wiederhergestellt" - msgid "unknown" msgstr "unbekannt" @@ -870,3 +867,21 @@ msgstr "{0, plural, one {{1} Datei wird verschlüsselt und hochgeladen} other {{ msgid "{0, plural, one {You are about to delete {1} item.} other {You are about to delete {2} items.}}" msgstr "{0, plural, one {Sie sind dabei, {1} Artikel zu löschen.} other {Sie sind dabei, {2} Artikel zu löschen.}}" + +msgid "{0} cancelled" +msgstr "" + +msgid "{0} cancelled - {successCount} files {1} successfully" +msgstr "" + +msgid "{0} complete" +msgstr "" + +msgid "{0} failed" +msgstr "" + +msgid "{0} {fileProgress} - {1}" +msgstr "" + +msgid "{successCount} files transferred successfully, {0} failed" +msgstr "" diff --git a/packages/files-ui/src/locales/en/messages.po b/packages/files-ui/src/locales/en/messages.po index d6d753b165..cbd244e49d 100644 --- a/packages/files-ui/src/locales/en/messages.po +++ b/packages/files-ui/src/locales/en/messages.po @@ -43,9 +43,6 @@ msgstr "Add more files" msgid "Add viewers and editors by username, sharing id or Ethereum address." msgstr "Add viewers and editors by username, sharing id or Ethereum address." -msgid "An error occurred while downloading the file" -msgstr "An error occurred while downloading the file" - msgid "An error occurred:" msgstr "An error occurred:" @@ -142,6 +139,9 @@ msgstr "Copy over" msgid "Copy to" msgstr "Copy to" +msgid "Copying files" +msgstr "Copying files" + msgid "Create" msgstr "Create" @@ -166,6 +166,18 @@ msgstr "Create your public username in <0>Settings!" msgid "Dark Theme" msgstr "Dark Theme" +msgid "Data deleted successfully" +msgstr "Data deleted successfully" + +msgid "Data moved successfully" +msgstr "Data moved successfully" + +msgid "Data moved to bin successfully" +msgstr "Data moved to bin successfully" + +msgid "Data restored successfully" +msgstr "Data restored successfully" + msgid "Date uploaded" msgstr "Date uploaded" @@ -220,9 +232,6 @@ msgstr "Drop to upload files" msgid "Email is required" msgstr "Email is required" -msgid "Encrypting & uploading" -msgstr "Encrypting & uploading" - msgid "Enter backup secret phrase:" msgstr "Enter backup secret phrase:" @@ -253,9 +262,6 @@ msgstr "" "If you are using a contract wallet, please make \n" "sure you have activated your wallet." -msgid "File" -msgstr "File" - msgid "File Info" msgstr "File Info" @@ -277,9 +283,6 @@ msgstr "Files sharing key" msgid "First name" msgstr "First name" -msgid "Folder" -msgstr "Folder" - msgid "Folder name is already in use" msgstr "Folder name is already in use" @@ -343,8 +346,8 @@ msgstr "Info" msgid "I’m done saving my backup secret phrase" msgstr "I’m done saving my backup secret phrase" -msgid "Keep original file" -msgstr "Keep original file" +msgid "Keep original files" +msgstr "Keep original files" msgid "Language" msgstr "Language" @@ -421,6 +424,12 @@ msgstr "Nice to see you again!" msgid "No file to download." msgstr "No file to download." +msgid "No files to copy" +msgstr "No files to copy" + +msgid "No files to share" +msgstr "No files to share" + msgid "No files to show" msgstr "No files to show" @@ -616,6 +625,9 @@ msgstr "Share" msgid "Share file" msgstr "Share file" +msgid "Share selected" +msgstr "Share selected" + msgid "Shared" msgstr "Shared" @@ -628,11 +640,8 @@ msgstr "Shared folders" msgid "Shared with" msgstr "Shared with" -msgid "Sharing cancelled" -msgstr "Sharing cancelled" - -msgid "Sharing your file (Downloading)" -msgstr "Sharing your file (Downloading)" +msgid "Sharing files" +msgstr "Sharing files" msgid "Sign Out" msgstr "Sign Out" @@ -709,8 +718,11 @@ msgstr "There was an error authenticating" msgid "There was an error connecting your wallet" msgstr "There was an error connecting your wallet" -msgid "There was an error deleting this" -msgstr "There was an error deleting this" +msgid "There was an error creating the folder {0}" +msgstr "There was an error creating the folder {0}" + +msgid "There was an error deleting your data" +msgstr "There was an error deleting your data" msgid "There was an error getting search results" msgstr "There was an error getting search results" @@ -718,11 +730,11 @@ msgstr "There was an error getting search results" msgid "There was an error getting the preview." msgstr "There was an error getting the preview." -msgid "There was an error moving this" -msgstr "There was an error moving this" +msgid "There was an error moving your data" +msgstr "There was an error moving your data" -msgid "There was an error recovering this" -msgstr "There was an error recovering this" +msgid "There was an error restoring your data" +msgstr "There was an error restoring your data" msgid "There was an error when setting username." msgstr "There was an error when setting username." @@ -739,9 +751,6 @@ msgstr "This website uses cookies" msgid "This website uses cookies that help the website function and track interactions for analytics purposes. You have the right to decline our use of cookies. For us to provide a customizable user experience to you, please click on the Accept button below.<0>Learn more" msgstr "This website uses cookies that help the website function and track interactions for analytics purposes. You have the right to decline our use of cookies. For us to provide a customizable user experience to you, please click on the Accept button below.<0>Learn more" -msgid "Transfer complete" -msgstr "Transfer complete" - msgid "Try again" msgstr "Try again" @@ -841,27 +850,12 @@ msgstr "You will need to sign a message in your wallet to complete sign in." msgid "Your recovery key can be used to restore your account in place of your backup secret phrase." msgstr "Your recovery key can be used to restore your account in place of your backup secret phrase." -msgid "deleted successfully" -msgstr "deleted successfully" - -msgid "file" -msgstr "file" - -msgid "folder" -msgstr "folder" - msgid "me" msgstr "me" -msgid "moved successfully" -msgstr "moved successfully" - msgid "on" msgstr "on" -msgid "recovered successfully" -msgstr "recovered successfully" - msgid "unknown" msgstr "unknown" @@ -873,3 +867,21 @@ msgstr "{0, plural, one {Encrypting and uploading {1} file} other {Encrypting an msgid "{0, plural, one {You are about to delete {1} item.} other {You are about to delete {2} items.}}" msgstr "{0, plural, one {You are about to delete {1} item.} other {You are about to delete {2} items.}}" + +msgid "{0} cancelled" +msgstr "{0} cancelled" + +msgid "{0} cancelled - {successCount} files {1} successfully" +msgstr "{0} cancelled - {successCount} files {1} successfully" + +msgid "{0} complete" +msgstr "{0} complete" + +msgid "{0} failed" +msgstr "{0} failed" + +msgid "{0} {fileProgress} - {1}" +msgstr "{0} {fileProgress} - {1}" + +msgid "{successCount} files transferred successfully, {0} failed" +msgstr "{successCount} files transferred successfully, {0} failed" diff --git a/packages/files-ui/src/locales/es/messages.po b/packages/files-ui/src/locales/es/messages.po index e14352407e..a7aaf63fd4 100644 --- a/packages/files-ui/src/locales/es/messages.po +++ b/packages/files-ui/src/locales/es/messages.po @@ -1,18 +1,18 @@ msgid "" msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-05-06 20:51+0200\n" -"Mime-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 2.4.3\n" +"PO-Revision-Date: 2021-09-30 12:40+0000\n" +"Last-Translator: Anonymous \n" +"Language-Team: Spanish \n" "Language: es\n" -"Project-Id-Version: \n" -"PO-Revision-Date: \n" -"Last-Translator: \n" -"Language-Team: \n" "MIME-Version: 1.0\n" -"Report-Msgid-Bugs-To: \n" -"Plural-Forms: \n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.9-dev\n" +"Mime-Version: 1.0\n" msgid "A backup secret phrase will be generated and used for your account.<0/>We do not store it and <1>it can only be displayed once. Save it somewhere safe!" msgstr "" @@ -44,9 +44,6 @@ msgstr "Agrega mas archivos" msgid "Add viewers and editors by username, sharing id or Ethereum address." msgstr "" -msgid "An error occurred while downloading the file" -msgstr "" - msgid "An error occurred:" msgstr "" @@ -143,11 +140,14 @@ msgstr "" msgid "Copy to" msgstr "" +msgid "Copying files" +msgstr "" + msgid "Create" msgstr "Crear" msgid "Create Folder" -msgstr "Crear Carpeta" +msgstr "" msgid "Create Shared Folder" msgstr "" @@ -167,6 +167,18 @@ msgstr "" msgid "Dark Theme" msgstr "Tema oscuro" +msgid "Data deleted successfully" +msgstr "" + +msgid "Data moved successfully" +msgstr "" + +msgid "Data moved to bin successfully" +msgstr "" + +msgid "Data restored successfully" +msgstr "" + msgid "Date uploaded" msgstr "Fecha de subida" @@ -221,9 +233,6 @@ msgstr "Suelta para subir archivos" msgid "Email is required" msgstr "" -msgid "Encrypting & uploading" -msgstr "" - msgid "Enter backup secret phrase:" msgstr "" @@ -254,9 +263,6 @@ msgstr "" "Si está utilizando una billetera de contrato, haga\n" "seguro que has activado tu billetera." -msgid "File" -msgstr "Archivo" - msgid "File Info" msgstr "Información del archivo" @@ -278,9 +284,6 @@ msgstr "" msgid "First name" msgstr "Primer Nombre" -msgid "Folder" -msgstr "Archivo" - msgid "Folder name is already in use" msgstr "" @@ -344,7 +347,7 @@ msgstr "Info" msgid "I’m done saving my backup secret phrase" msgstr "" -msgid "Keep original file" +msgid "Keep original files" msgstr "" msgid "Language" @@ -422,6 +425,12 @@ msgstr "Encantado de verte de nuevo!" msgid "No file to download." msgstr "" +msgid "No files to copy" +msgstr "" + +msgid "No files to share" +msgstr "" + msgid "No files to show" msgstr "No hay archivos para mostrar" @@ -441,7 +450,7 @@ msgid "Number of copies (Replication Factor)" msgstr "Número de copias (factor de replicación)" msgid "OK" -msgstr "OK" +msgstr "" msgid "One sec, getting files ready…" msgstr "" @@ -617,6 +626,9 @@ msgstr "" msgid "Share file" msgstr "" +msgid "Share selected" +msgstr "" + msgid "Shared" msgstr "" @@ -629,10 +641,7 @@ msgstr "" msgid "Shared with" msgstr "" -msgid "Sharing cancelled" -msgstr "" - -msgid "Sharing your file (Downloading)" +msgid "Sharing files" msgstr "" msgid "Sign Out" @@ -710,8 +719,11 @@ msgstr "Hubo un error de autenticación." msgid "There was an error connecting your wallet" msgstr "Hubo un error al conectar su billetera" -msgid "There was an error deleting this" -msgstr "Hubo un error al eliminar esto." +msgid "There was an error creating the folder {0}" +msgstr "" + +msgid "There was an error deleting your data" +msgstr "" msgid "There was an error getting search results" msgstr "Se produjo un error al obtener los resultados de la búsqueda." @@ -719,11 +731,11 @@ msgstr "Se produjo un error al obtener los resultados de la búsqueda." msgid "There was an error getting the preview." msgstr "Hubo un error al obtener la vista previa." -msgid "There was an error moving this" +msgid "There was an error moving your data" msgstr "" -msgid "There was an error recovering this" -msgstr "Hubo un error al recuperar esto." +msgid "There was an error restoring your data" +msgstr "" msgid "There was an error when setting username." msgstr "" @@ -740,9 +752,6 @@ msgstr "" msgid "This website uses cookies that help the website function and track interactions for analytics purposes. You have the right to decline our use of cookies. For us to provide a customizable user experience to you, please click on the Accept button below.<0>Learn more" msgstr "" -msgid "Transfer complete" -msgstr "" - msgid "Try again" msgstr "Intentar otra vez" @@ -842,27 +851,12 @@ msgstr "Deberá firmar un mensaje en su billetera para completar el inicio de se msgid "Your recovery key can be used to restore your account in place of your backup secret phrase." msgstr "" -msgid "deleted successfully" -msgstr "borrado exitosamente" - -msgid "file" -msgstr "archivo" - -msgid "folder" -msgstr "carpeta" - msgid "me" msgstr "" -msgid "moved successfully" -msgstr "" - msgid "on" msgstr "en" -msgid "recovered successfully" -msgstr "recuperado con éxito" - msgid "unknown" msgstr "" @@ -874,3 +868,21 @@ msgstr "" msgid "{0, plural, one {You are about to delete {1} item.} other {You are about to delete {2} items.}}" msgstr "" + +msgid "{0} cancelled" +msgstr "" + +msgid "{0} cancelled - {successCount} files {1} successfully" +msgstr "" + +msgid "{0} complete" +msgstr "" + +msgid "{0} failed" +msgstr "" + +msgid "{0} {fileProgress} - {1}" +msgstr "" + +msgid "{successCount} files transferred successfully, {0} failed" +msgstr "" diff --git a/packages/files-ui/src/locales/fr/messages.po b/packages/files-ui/src/locales/fr/messages.po index a187a80dbe..27b41850de 100644 --- a/packages/files-ui/src/locales/fr/messages.po +++ b/packages/files-ui/src/locales/fr/messages.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-23 11:05+0200\n" -"PO-Revision-Date: 2021-09-22 21:38+0000\n" +"PO-Revision-Date: 2021-10-09 17:23+0000\n" "Last-Translator: J. Lavoie \n" "Language-Team: French \n" "Language: fr\n" @@ -18,7 +18,7 @@ msgid "A backup secret phrase will be generated and used for your account.<0/>We msgstr "Une phrase secrète de sauvegarde sera générée et utilisé pour ce compte.<0/>Nous ne la sauvergardons pas <1>elle ne peut être affichée qu’une seule fois. Gardez-la dans un endroit sûr !" msgid "A better sharing experience is coming soon." -msgstr "" +msgstr "Une meilleure expérience de partage sera bientôt disponible." msgid "A file with the same name already exists" msgstr "Un fichier avec ce nom existe déjà" @@ -44,9 +44,6 @@ msgstr "Ajouter d’autres fichiers" msgid "Add viewers and editors by username, sharing id or Ethereum address." msgstr "Ajoutez des personnes pouvant visualiser ou afficher par nom d'utilisateur, identifiant de partage ou adresse Ethereum." -msgid "An error occurred while downloading the file" -msgstr "Une erreur s'est produite lors du téléchargement du fichier" - msgid "An error occurred:" msgstr "Une erreur s'est produite :" @@ -143,11 +140,14 @@ msgstr "Copier" msgid "Copy to" msgstr "Copier vers" +msgid "Copying files" +msgstr "Copie de fichiers" + msgid "Create" msgstr "Créer" msgid "Create Folder" -msgstr "Créer un dossier" +msgstr "" msgid "Create Shared Folder" msgstr "Créer un dossier partagé" @@ -167,6 +167,18 @@ msgstr "Créez votre nom d'utilisateur public dans <0>Paramètres !" msgid "Dark Theme" msgstr "Thème sombre" +msgid "Data deleted successfully" +msgstr "Données supprimées avec succès" + +msgid "Data moved successfully" +msgstr "Données déplacées avec succès" + +msgid "Data moved to bin successfully" +msgstr "Les données ont été déplacées vers la poubelle avec succès" + +msgid "Data restored successfully" +msgstr "Données restaurées avec succès" + msgid "Date uploaded" msgstr "Téléversé le" @@ -221,9 +233,6 @@ msgstr "Faire glisser pour téléverser un fichier" msgid "Email is required" msgstr "Un courriel est requis" -msgid "Encrypting & uploading" -msgstr "Chiffrement et téléversement" - msgid "Enter backup secret phrase:" msgstr "Phrase secrète de sauvegarde :" @@ -254,9 +263,6 @@ msgstr "" "Si vous utilisez un contract wallet, veuillez\n" "vérifier que vous avez activé votre wallet." -msgid "File" -msgstr "Fichier" - msgid "File Info" msgstr "Infos du fichier" @@ -278,11 +284,8 @@ msgstr "Clé de partage des fichiers" msgid "First name" msgstr "Prénom" -msgid "Folder" -msgstr "Dossier" - msgid "Folder name is already in use" -msgstr "Le nom du dossier est déjà utilisé" +msgstr "" msgid "Folder uploads are not supported currently" msgstr "Le téléversement de dossiers n'est pas actuellement pris en charge" @@ -344,8 +347,8 @@ msgstr "Infos" msgid "I’m done saving my backup secret phrase" msgstr "Phrase de sauvegarde secrète enregistrée" -msgid "Keep original file" -msgstr "Conserver le fichier original" +msgid "Keep original files" +msgstr "Conserver les fichiers originaux" msgid "Language" msgstr "Langue" @@ -422,6 +425,12 @@ msgstr "Ravi de te revoir !" msgid "No file to download." msgstr "Aucun fichier à télécharger." +msgid "No files to copy" +msgstr "Aucun fichier à copier" + +msgid "No files to share" +msgstr "Aucun fichier à partager" + msgid "No files to show" msgstr "Aucun fichier à afficher" @@ -441,7 +450,7 @@ msgid "Number of copies (Replication Factor)" msgstr "Nombre de copies (facteur de réplication)" msgid "OK" -msgstr "OK" +msgstr "" msgid "One sec, getting files ready…" msgstr "Un instant, nous préparons les fichiers…" @@ -546,7 +555,7 @@ msgid "Report a File" msgstr "Signaler un fichier" msgid "Report a bug" -msgstr "" +msgstr "Signaler une erreur" msgid "Requested from" msgstr "Envoyé par" @@ -617,6 +626,9 @@ msgstr "Partager" msgid "Share file" msgstr "Partager le fichier" +msgid "Share selected" +msgstr "Partager la sélection" + msgid "Shared" msgstr "Partagé" @@ -629,11 +641,8 @@ msgstr "Dossiers partagés" msgid "Shared with" msgstr "Partagé avec" -msgid "Sharing cancelled" -msgstr "Partage annulé" - -msgid "Sharing your file (Downloading)" -msgstr "Partager votre fichier (Téléchargement)" +msgid "Sharing files" +msgstr "Partage des fichiers" msgid "Sign Out" msgstr "Se déconnecter" @@ -645,7 +654,7 @@ msgid "Sign in with a different account" msgstr "Se connecter avec un autre compte" msgid "Sign me up!" -msgstr "" +msgstr "S'inscrire !" msgid "Sign-in methods" msgstr "Méthodes de connexion" @@ -672,7 +681,7 @@ msgid "Start Upload" msgstr "Démarrer le téléversement" msgid "Start a team" -msgstr "" +msgstr "Créer une équipe" msgid "Storage Plan" msgstr "Plan de stockage" @@ -681,7 +690,7 @@ msgid "Stored by miner" msgstr "Sauvegardé par le mineur" msgid "Teams" -msgstr "" +msgstr "Équipes" msgid "Technical" msgstr "Technique" @@ -710,8 +719,11 @@ msgstr "Une erreur s’est produite lors de l’authentification" msgid "There was an error connecting your wallet" msgstr "Une erreur s’est produite lors de la connexion de votre wallet" -msgid "There was an error deleting this" -msgstr "Une erreur s’est produite lors de la suppression" +msgid "There was an error creating the folder {0}" +msgstr "" + +msgid "There was an error deleting your data" +msgstr "Une erreur s'est produite lors de la suppression de vos données" msgid "There was an error getting search results" msgstr "Une erreur s’est produite lors de l’obtention des résultats de recherche" @@ -719,14 +731,14 @@ msgstr "Une erreur s’est produite lors de l’obtention des résultats de rech msgid "There was an error getting the preview." msgstr "Une erreur s’est produite lors de la génération de l’aperçu." -msgid "There was an error moving this" -msgstr "Une erreur s’est produite lors du déplacement" +msgid "There was an error moving your data" +msgstr "Une erreur s'est produite lors du transfert de vos données" -msgid "There was an error recovering this" -msgstr "Une erreur s’est produite lors de la récupération" +msgid "There was an error restoring your data" +msgstr "Une erreur s'est produite lors de la restauration de vos données" msgid "There was an error when setting username." -msgstr "Il y a eu une erreur dans le paramétrage du nom d’utilisateur." +msgstr "Une erreur s'est produite lors de la définition du nom d'utilisateur." msgid "This username is already taken" msgstr "Ce nom d’utilisateur est déjà pris" @@ -740,9 +752,6 @@ msgstr "Ce site web utilise des cookies" msgid "This website uses cookies that help the website function and track interactions for analytics purposes. You have the right to decline our use of cookies. For us to provide a customizable user experience to you, please click on the Accept button below.<0>Learn more" msgstr "Ce site web utilise des cookies qui l'aident à fonctionner et à suivre les interactions à des fins d'analyse. Vous avez le droit de refuser notre utilisation des cookies. Pour que nous puissions vous offrir une expérience utilisateur personnalisable, veuillez cliquer sur le bouton Accepter ci-dessous.<0>En savoir plus" -msgid "Transfer complete" -msgstr "Transfert terminé" - msgid "Try again" msgstr "Essayer de nouveau" @@ -842,27 +851,12 @@ msgstr "Vous devrez signer un message avec votre wallet pour terminer la procéd msgid "Your recovery key can be used to restore your account in place of your backup secret phrase." msgstr "Votre clé de récupération peut être utilisée pour restaurer votre compte à la place de votre phrase de sauvegarde secrète." -msgid "deleted successfully" -msgstr "supprimé avec succès" - -msgid "file" -msgstr "fichier" - -msgid "folder" -msgstr "dossier" - msgid "me" msgstr "moi" -msgid "moved successfully" -msgstr "déplacé avec succès" - msgid "on" msgstr "le" -msgid "recovered successfully" -msgstr "récupéré avec succès" - msgid "unknown" msgstr "inconnu" @@ -874,3 +868,21 @@ msgstr "{0, plural, one {Chiffrement et téléversement de {1} fichier} other {C msgid "{0, plural, one {You are about to delete {1} item.} other {You are about to delete {2} items.}}" msgstr "{0, plural, one {Vous êtes sur le point de supprimer {1} élément.} other {Vous êtes sur le point de supprimer {2} éléments.}}" + +msgid "{0} cancelled" +msgstr "{0} annulé(s)" + +msgid "{0} cancelled - {successCount} files {1} successfully" +msgstr "{0} annulé – {successCount} fichiers {1} avec succès" + +msgid "{0} complete" +msgstr "{0} terminé" + +msgid "{0} failed" +msgstr "échec de {0}" + +msgid "{0} {fileProgress} - {1}" +msgstr "{0} {fileProgress} – {1}" + +msgid "{successCount} files transferred successfully, {0} failed" +msgstr "{successCount} fichiers transférés avec succès, {0} échec(s)" diff --git a/packages/files-ui/src/locales/no/messages.po b/packages/files-ui/src/locales/no/messages.po index b958ba8d47..348339e91e 100644 --- a/packages/files-ui/src/locales/no/messages.po +++ b/packages/files-ui/src/locales/no/messages.po @@ -3,14 +3,14 @@ msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-20 00:28+0200\n" -"PO-Revision-Date: 2021-07-29 09:32+0000\n" +"PO-Revision-Date: 2021-09-30 12:40+0000\n" "Last-Translator: Allan Nordhøy \n" "Language-Team: Norwegian Bokmål \n" "Language: no\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.7.2-dev\n" +"X-Generator: Weblate 4.9-dev\n" "Mime-Version: 1.0\n" msgid "A backup secret phrase will be generated and used for your account.<0/>We do not store it and <1>it can only be displayed once. Save it somewhere safe!" @@ -43,9 +43,6 @@ msgstr "Legg til flere filer" msgid "Add viewers and editors by username, sharing id or Ethereum address." msgstr "" -msgid "An error occurred while downloading the file" -msgstr "" - msgid "An error occurred:" msgstr "" @@ -142,11 +139,14 @@ msgstr "" msgid "Copy to" msgstr "" +msgid "Copying files" +msgstr "" + msgid "Create" msgstr "Opprett" msgid "Create Folder" -msgstr "Opprett mappe" +msgstr "" msgid "Create Shared Folder" msgstr "" @@ -166,6 +166,18 @@ msgstr "" msgid "Dark Theme" msgstr "Mørk drakt" +msgid "Data deleted successfully" +msgstr "" + +msgid "Data moved successfully" +msgstr "" + +msgid "Data moved to bin successfully" +msgstr "" + +msgid "Data restored successfully" +msgstr "" + msgid "Date uploaded" msgstr "Dato opplastet" @@ -220,9 +232,6 @@ msgstr "Dra for å laste opp filer" msgid "Email is required" msgstr "E-post kreves" -msgid "Encrypting & uploading" -msgstr "" - msgid "Enter backup secret phrase:" msgstr "" @@ -250,9 +259,6 @@ msgid "" "sure you have activated your wallet." msgstr "" -msgid "File" -msgstr "Fil" - msgid "File Info" msgstr "Filinfo" @@ -274,9 +280,6 @@ msgstr "" msgid "First name" msgstr "Fornavn" -msgid "Folder" -msgstr "Mappe" - msgid "Folder name is already in use" msgstr "" @@ -340,7 +343,7 @@ msgstr "Info" msgid "I’m done saving my backup secret phrase" msgstr "" -msgid "Keep original file" +msgid "Keep original files" msgstr "" msgid "Language" @@ -418,6 +421,12 @@ msgstr "" msgid "No file to download." msgstr "" +msgid "No files to copy" +msgstr "" + +msgid "No files to share" +msgstr "" + msgid "No files to show" msgstr "Ingen filer å vise" @@ -437,7 +446,7 @@ msgid "Number of copies (Replication Factor)" msgstr "" msgid "OK" -msgstr "OK" +msgstr "" msgid "One sec, getting files ready…" msgstr "" @@ -613,6 +622,9 @@ msgstr "" msgid "Share file" msgstr "" +msgid "Share selected" +msgstr "" + msgid "Shared" msgstr "Delt" @@ -625,10 +637,7 @@ msgstr "" msgid "Shared with" msgstr "" -msgid "Sharing cancelled" -msgstr "" - -msgid "Sharing your file (Downloading)" +msgid "Sharing files" msgstr "" msgid "Sign Out" @@ -706,7 +715,10 @@ msgstr "" msgid "There was an error connecting your wallet" msgstr "" -msgid "There was an error deleting this" +msgid "There was an error creating the folder {0}" +msgstr "" + +msgid "There was an error deleting your data" msgstr "" msgid "There was an error getting search results" @@ -715,10 +727,10 @@ msgstr "" msgid "There was an error getting the preview." msgstr "" -msgid "There was an error moving this" +msgid "There was an error moving your data" msgstr "" -msgid "There was an error recovering this" +msgid "There was an error restoring your data" msgstr "" msgid "There was an error when setting username." @@ -736,9 +748,6 @@ msgstr "" msgid "This website uses cookies that help the website function and track interactions for analytics purposes. You have the right to decline our use of cookies. For us to provide a customizable user experience to you, please click on the Accept button below.<0>Learn more" msgstr "" -msgid "Transfer complete" -msgstr "" - msgid "Try again" msgstr "Prøv igjen" @@ -838,27 +847,12 @@ msgstr "" msgid "Your recovery key can be used to restore your account in place of your backup secret phrase." msgstr "" -msgid "deleted successfully" -msgstr "slettet" - -msgid "file" -msgstr "fil" - -msgid "folder" -msgstr "mappe" - msgid "me" msgstr "" -msgid "moved successfully" -msgstr "flyttet" - msgid "on" msgstr "" -msgid "recovered successfully" -msgstr "gjenopprettet" - msgid "unknown" msgstr "" @@ -870,3 +864,21 @@ msgstr "" msgid "{0, plural, one {You are about to delete {1} item.} other {You are about to delete {2} items.}}" msgstr "" + +msgid "{0} cancelled" +msgstr "" + +msgid "{0} cancelled - {successCount} files {1} successfully" +msgstr "" + +msgid "{0} complete" +msgstr "" + +msgid "{0} failed" +msgstr "" + +msgid "{0} {fileProgress} - {1}" +msgstr "" + +msgid "{successCount} files transferred successfully, {0} failed" +msgstr "" diff --git a/packages/gaming-ui/package.json b/packages/gaming-ui/package.json index 22d3bdd943..e3029a6be3 100644 --- a/packages/gaming-ui/package.json +++ b/packages/gaming-ui/package.json @@ -6,7 +6,7 @@ "@babel/core": "^7.12.10", "@babel/runtime": "^7.0.0", "@chainsafe/browser-storage-hooks": "^1.0.1", - "@chainsafe/files-api-client": "^1.18.10", + "@chainsafe/files-api-client": "1.18.15", "@chainsafe/web3-context": "1.1.4", "@lingui/core": "^3.7.2", "@lingui/react": "^3.7.2", @@ -56,7 +56,7 @@ "@types/yup": "^0.29.9", "@types/zxcvbn": "^4.4.0", "babel-plugin-macros": "^2.8.0", - "cypress": "^8.4", + "cypress": "^8.6", "cypress-file-upload": "^5.0.8", "cypress-pipe": "^2.0.0" }, diff --git a/packages/gaming-ui/src/Components/Modules/LoginModule.tsx b/packages/gaming-ui/src/Components/Modules/LoginModule.tsx index 85faf0bba4..c4268a24c0 100644 --- a/packages/gaming-ui/src/Components/Modules/LoginModule.tsx +++ b/packages/gaming-ui/src/Components/Modules/LoginModule.tsx @@ -176,21 +176,20 @@ const LoginModule = ({ className }: IInitialScreen) => { await login(loginType) } catch (error: any) { let errorMessage = t`There was an error authenticating` - console.log(error) - if (Array.isArray(error) && error[0]) { - if ( - error[0].type === "signature" && - error[0].message === "Invalid signature" - ) { - errorMessage = t`Failed to validate signature. + + // Invalid signature, or contract wallet not deployed + if (error?.error?.code === 403 && error?.error?.message?.includes("Invalid signature")) { + errorMessage = t`Failed to validate signature. If you are using a contract wallet, please make sure you have activated your wallet.` - } } - // WalletConnect be sassy + + // User rejected the signature request (WalletConnect be sassy) if (error?.message === "Just nope" || error?.code === 4001) { errorMessage = t`Failed to get signature` } + + // DirectAuth popup was closed if (error?.message === "user closed popup") { errorMessage = t`The authentication popup was closed` } diff --git a/packages/storage-ui/package.json b/packages/storage-ui/package.json index 58da774b9e..b36126a35b 100644 --- a/packages/storage-ui/package.json +++ b/packages/storage-ui/package.json @@ -6,7 +6,7 @@ "@babel/core": "^7.12.10", "@babel/runtime": "^7.0.0", "@chainsafe/browser-storage-hooks": "^1.0.1", - "@chainsafe/files-api-client": "^1.18.10", + "@chainsafe/files-api-client": "1.18.15", "@chainsafe/web3-context": "1.1.4", "@lingui/core": "^3.7.2", "@lingui/react": "^3.7.2", @@ -64,7 +64,7 @@ "@types/yup": "^0.29.9", "@types/zxcvbn": "^4.4.0", "babel-plugin-macros": "^2.8.0", - "cypress": "^8.4", + "cypress": "^8.6", "cypress-file-upload": "^5.0.8", "cypress-pipe": "^2.0.0" }, diff --git a/packages/storage-ui/src/Components/Modules/CreateFolderModal/CreateFolderModal.tsx b/packages/storage-ui/src/Components/Modules/CreateFolderModal/CreateFolderModal.tsx index 6b245096ec..3cfadf65c8 100644 --- a/packages/storage-ui/src/Components/Modules/CreateFolderModal/CreateFolderModal.tsx +++ b/packages/storage-ui/src/Components/Modules/CreateFolderModal/CreateFolderModal.tsx @@ -110,13 +110,14 @@ const CreateFolderModal = ({ modalOpen, close }: ICreateFolderModalProps) => { setCreatingFolder(false) helpers.resetForm() close() - } catch (errors: any) { + } catch (error: any) { setCreatingFolder(false) - if (errors[0].message.includes("Entry with such name can")) { + if (error?.error?.code === 409) { helpers.setFieldError("name", t`Folder name is already in use`) } else { - helpers.setFieldError("name", errors[0].message) + helpers.setFieldError("name", t`There was an error creating the folder ${error?.message}`) } + helpers.setSubmitting(false) } helpers.setSubmitting(false) }} diff --git a/packages/storage-ui/src/Components/Modules/LoginModule.tsx b/packages/storage-ui/src/Components/Modules/LoginModule.tsx index 42bc1eb818..6cafd0cb3a 100644 --- a/packages/storage-ui/src/Components/Modules/LoginModule.tsx +++ b/packages/storage-ui/src/Components/Modules/LoginModule.tsx @@ -203,26 +203,26 @@ const LoginModule = ({ className }: IInitialScreen) => { setLoginMode(loginType) try { await login(loginType) - } catch (error) { + } catch (error: any) { let errorMessage = t`There was an error authenticating` - console.log(error) - if (Array.isArray(error) && error[0]) { - if ( - error[0].type === "signature" && - error[0].message === "Invalid signature" - ) { - errorMessage = t`Failed to validate signature. + + // Invalid signature, or contract wallet not deployed + if (error?.error?.code === 403 && error?.error?.message?.includes("Invalid signature")) { + errorMessage = t`Failed to validate signature. If you are using a contract wallet, please make sure you have activated your wallet.` - } } - // WalletConnect be sassy - if ((error instanceof Error && error.message === "Just nope") || ((error as any).code === 4001)) { + + // User rejected the signature request (WalletConnect be sassy) + if (error?.message === "Just nope" || error?.code === 4001) { errorMessage = t`Failed to get signature` } - if (error instanceof Error && error.message === "user closed popup") { + + // DirectAuth popup was closed + if (error?.message === "user closed popup") { errorMessage = t`The authentication popup was closed` } + setError(errorMessage) } setIsConnecting(false) diff --git a/packages/storage-ui/src/Components/Modules/UploadFileModal/UploadFileModal.tsx b/packages/storage-ui/src/Components/Modules/UploadFileModal/UploadFileModal.tsx index 0280a90e83..6a6a203f63 100644 --- a/packages/storage-ui/src/Components/Modules/UploadFileModal/UploadFileModal.tsx +++ b/packages/storage-ui/src/Components/Modules/UploadFileModal/UploadFileModal.tsx @@ -94,12 +94,8 @@ const UploadFileModal = ({ modalOpen, close }: IUploadFileModuleProps) => { await uploadFiles(bucket.id, values.files, currentPath) refreshContents && refreshContents() helpers.resetForm() - } catch (errors: any) { - if (errors[0].message.includes("conflict with existing")) { - helpers.setFieldError("files", t`File/Folder already exists`) - } else { - helpers.setFieldError("files", errors[0].message) - } + } catch (error: any) { + console.error(error) } helpers.setSubmitting(false) }, [close, currentPath, uploadFiles, refreshContents, bucket]) diff --git a/packages/storage-ui/src/Contexts/StorageContext.tsx b/packages/storage-ui/src/Contexts/StorageContext.tsx index 057c500387..1b64d05c54 100644 --- a/packages/storage-ui/src/Contexts/StorageContext.tsx +++ b/packages/storage-ui/src/Contexts/StorageContext.tsx @@ -248,13 +248,12 @@ const StorageProvider = ({ children }: StorageContextProps) => { }, REMOVE_UPLOAD_PROGRESS_DELAY) return Promise.resolve() - } catch (error) { - console.error(error) + } catch (error: any) { // setting error let errorMessage = t`Something went wrong. We couldn't upload your file` // we will need a method to parse server errors - if (Array.isArray(error) && error[0].message.includes("conflict")) { + if (error?.error?.code === 409) { errorMessage = t`A file with the same name already exists` } dispatchUploadsInProgress({ diff --git a/packages/storage-ui/src/locales/en/messages.po b/packages/storage-ui/src/locales/en/messages.po index 3f2656b39a..9cdeb3934e 100644 --- a/packages/storage-ui/src/locales/en/messages.po +++ b/packages/storage-ui/src/locales/en/messages.po @@ -178,9 +178,6 @@ msgstr "" msgid "File" msgstr "File" -msgid "File/Folder already exists" -msgstr "File/Folder already exists" - msgid "Folder" msgstr "Folder" @@ -361,6 +358,9 @@ msgstr "There was an error authenticating" msgid "There was an error connecting your wallet" msgstr "There was an error connecting your wallet" +msgid "There was an error creating the folder {0}" +msgstr "There was an error creating the folder {0}" + msgid "There was an error deleting this item" msgstr "There was an error deleting this item" diff --git a/yarn.lock b/yarn.lock index 5cad93d39a..3ab71bfd2f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1925,10 +1925,10 @@ resolved "https://registry.yarnpkg.com/@chainsafe/browser-storage-hooks/-/browser-storage-hooks-1.0.1.tgz#26d32cde1999914db755a631e2643823c54959f7" integrity sha512-Q4b5gQAZnsRXKeADspd5isqfwwhhXjDk70y++YadufA6EZ3tf340oW0OVszp74KaGEw+CAYFGQR4X7bzpZ3x9Q== -"@chainsafe/files-api-client@^1.18.10": - version "1.18.10" - resolved "https://registry.yarnpkg.com/@chainsafe/files-api-client/-/files-api-client-1.18.10.tgz#a359f0d40916afec41ea7ffc8aa4ffc505c25c17" - integrity sha512-Rpuk7jDF0cFg53xIrfHsp20aA37QwYd/WDv28JjlhpBI9egbk6oTgVuB9LEiR9mYWb65CIXxfxGvc6WmE3DWTw== +"@chainsafe/files-api-client@1.18.15": + version "1.18.15" + resolved "https://registry.yarnpkg.com/@chainsafe/files-api-client/-/files-api-client-1.18.15.tgz#452572eb0ecb8178617d9faa37b7866bcfeeb4ec" + integrity sha512-W7MkZnK44dV1JixPavKKppi8KVhBk60uHoaDv/zRH0WVXT5QsWjQuCLpeWv9NcytHezsOv+5AAbovnjaZFwjpA== dependencies: "@redocly/openapi-cli" "^1.0.0-beta.58" "@redocly/openapi-core" "^1.0.0-beta.58" @@ -10715,10 +10715,10 @@ cypress-pipe@^2.0.0: resolved "https://registry.yarnpkg.com/cypress-pipe/-/cypress-pipe-2.0.0.tgz#577df7a70a8603d89a96dfe4092a605962181af8" integrity sha512-KW9s+bz4tFLucH3rBGfjW+Q12n7S4QpUSSyxiGrgPOfoHlbYWzAGB3H26MO0VTojqf9NVvfd5Kt0MH5XMgbfyg== -cypress@^8.4: - version "8.4.0" - resolved "https://registry.yarnpkg.com/cypress/-/cypress-8.4.0.tgz#09ec06a73f1cb10121c103cba15076e659e24876" - integrity sha512-RtVgGFR06ikyMaq/VqapeqOjGaIA42PpK7F0qe1MCiFArfUuJECsLmeYaOA+1TlmNUgJNMSF5fWKkZIJr5Uc7w== +cypress@^8.6: + version "8.6.0" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-8.6.0.tgz#8d02fa58878b37cfc45bbfce393aa974fa8a8e22" + integrity sha512-F7qEK/6Go5FsqTueR+0wEw2vOVKNgk5847Mys8vsWkzPoEKdxs+7N9Y1dit+zhaZCLtMPyrMwjfA53ZFy+lSww== dependencies: "@cypress/request" "^2.88.6" "@cypress/xvfb" "^1.2.4" @@ -10754,6 +10754,7 @@ cypress@^8.4: minimist "^1.2.5" ospath "^1.2.2" pretty-bytes "^5.6.0" + proxy-from-env "1.0.0" ramda "~0.27.1" request-progress "^3.0.0" supports-color "^8.1.1" @@ -20084,6 +20085,11 @@ proxy-addr@~2.0.5: forwarded "~0.1.2" ipaddr.js "1.9.1" +proxy-from-env@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee" + integrity sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4= + proxy-from-env@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"