diff --git a/src/components/pages/gallery/Upload.tsx b/src/components/pages/gallery/Upload.tsx index cccaa9556..77ad0e267 100644 --- a/src/components/pages/gallery/Upload.tsx +++ b/src/components/pages/gallery/Upload.tsx @@ -16,15 +16,17 @@ import uploadManager from 'services/upload/uploadManager'; import ImportService from 'services/importService'; import isElectron from 'is-electron'; import { METADATA_FOLDER_NAME } from 'constants/export'; -import { getUserFacingErrorMessage } from 'utils/error'; +import { CustomError } from 'utils/error'; import { Collection } from 'types/collection'; -import { SetLoading, SetFiles } from 'types/gallery'; +import { SetLoading, SetFiles, NotificationAttributes } from 'types/gallery'; import { FileUploadResults, UPLOAD_STAGES } from 'constants/upload'; import { ElectronFile, FileWithCollection } from 'types/upload'; import UploadTypeSelector from '../../UploadTypeSelector'; import Router from 'next/router'; import { isCanvasBlocked } from 'utils/upload/isCanvasBlocked'; import { downloadApp } from 'utils/common'; +import DiscFullIcon from '@mui/icons-material/DiscFull'; +import { logoutUser } from 'services/userService'; const FIRST_ALBUM_NAME = 'My First Album'; @@ -350,11 +352,9 @@ export default function Upload(props: Props) { collections ); } catch (err) { - const message = getUserFacingErrorMessage( - err.message, - galleryContext.showPlanSelectorModal + galleryContext.setNotificationAttributes( + getErrorNotification(err.message) ); - props.setBannerMessage(message); setProgressView(false); throw err; } finally { @@ -362,6 +362,7 @@ export default function Upload(props: Props) { props.syncWithRemote(); } }; + const retryFailed = async () => { try { props.setUploadInProgress(true); @@ -369,12 +370,9 @@ export default function Upload(props: Props) { await props.syncWithRemote(true, true); await uploadManager.retryFailedFiles(); } catch (err) { - const message = getUserFacingErrorMessage( - err.message, - galleryContext.showPlanSelectorModal + galleryContext.setNotificationAttributes( + getErrorNotification(err.message) ); - appContext.resetSharedFiles(); - props.setBannerMessage(message); setProgressView(false); } finally { props.setUploadInProgress(false); @@ -382,6 +380,45 @@ export default function Upload(props: Props) { } }; + function getErrorNotification(err: CustomError): NotificationAttributes { + switch (err) { + case CustomError.SESSION_EXPIRED: + return { + variant: 'danger', + message: constants.SESSION_EXPIRED, + action: { + text: constants.LOGIN, + callback: logoutUser, + }, + }; + case CustomError.SUBSCRIPTION_EXPIRED: + return { + variant: 'danger', + message: constants.SUBSCRIPTION_EXPIRED, + action: { + text: constants.UPGRADE_NOW, + callback: galleryContext.showPlanSelectorModal, + }, + }; + case CustomError.STORAGE_QUOTA_EXCEEDED: + return { + variant: 'danger', + message: constants.STORAGE_QUOTA_EXCEEDED, + action: { + text: constants.RENEW_NOW, + callback: galleryContext.showPlanSelectorModal, + }, + icon: , + }; + + default: + return { + variant: 'danger', + message: constants.UNKNOWN_ERROR, + }; + } + } + const uploadToSingleNewCollection = (collectionName: string) => { if (collectionName) { uploadFilesToNewCollections( diff --git a/src/types/gallery/index.ts b/src/types/gallery/index.ts index 8a694d01d..6f373708b 100644 --- a/src/types/gallery/index.ts +++ b/src/types/gallery/index.ts @@ -1,4 +1,5 @@ import { ButtonProps } from '@mui/material'; +import { ReactNode } from 'react'; import { Collection } from 'types/collection'; import { EnteFile } from 'types/file'; import { Search, SearchResultSummary } from 'types/search'; @@ -29,6 +30,7 @@ export type GalleryContextType = { }; export interface NotificationAttributes { + icon?: ReactNode; variant: ButtonProps['color']; message: JSX.Element | string; action?: { diff --git a/src/utils/error/index.ts b/src/utils/error/index.ts index 21e52cf76..620474c96 100644 --- a/src/utils/error/index.ts +++ b/src/utils/error/index.ts @@ -26,7 +26,7 @@ export enum CustomError { FILE_TOO_LARGE = 'file too large', SUBSCRIPTION_EXPIRED = 'subscription expired', STORAGE_QUOTA_EXCEEDED = 'storage quota exceeded', - SESSION_EXPIRED_MESSAGE = 'session expired', + SESSION_EXPIRED = 'session expired', TYPE_DETECTION_FAILED = 'type detection failed', SIGNUP_FAILED = 'signup failed', FAV_COLLECTION_MISSING = 'favorite collection missing', @@ -57,7 +57,7 @@ function parseUploadErrorCodes(error) { parsedMessage = CustomError.STORAGE_QUOTA_EXCEEDED; break; case ServerErrorCodes.SESSION_EXPIRED: - parsedMessage = CustomError.SESSION_EXPIRED_MESSAGE; + parsedMessage = CustomError.SESSION_EXPIRED; break; case ServerErrorCodes.FILE_TOO_LARGE: parsedMessage = CustomError.FILE_TOO_LARGE; @@ -78,28 +78,12 @@ export function handleUploadError(error): Error { switch (parsedError.message) { case CustomError.SUBSCRIPTION_EXPIRED: case CustomError.STORAGE_QUOTA_EXCEEDED: - case CustomError.SESSION_EXPIRED_MESSAGE: + case CustomError.SESSION_EXPIRED: throw parsedError; } return parsedError; } -export function getUserFacingErrorMessage( - err: CustomError, - action: () => void -) { - switch (err) { - case CustomError.SESSION_EXPIRED_MESSAGE: - return constants.SESSION_EXPIRED_MESSAGE; - case CustomError.SUBSCRIPTION_EXPIRED: - return constants.SUBSCRIPTION_EXPIRED(action); - case CustomError.STORAGE_QUOTA_EXCEEDED: - return constants.STORAGE_QUOTA_EXCEEDED(action); - default: - return constants.UNKNOWN_ERROR; - } -} - export function errorWithContext(originalError: Error, context: string) { const errorWithContext = new Error(context); errorWithContext.stack = diff --git a/src/utils/strings/englishConstants.tsx b/src/utils/strings/englishConstants.tsx index b90454342..fa51bb948 100644 --- a/src/utils/strings/englishConstants.tsx +++ b/src/utils/strings/englishConstants.tsx @@ -27,14 +27,6 @@ const Logo = styled.img` margin-top: -3px; `; -const Trigger = styled.span` - :hover { - text-decoration: underline; - cursor: pointer; - } - color: #51cd7c; -`; - const englishConstants = { ENTE: 'ente', HERO_HEADER: () => ( @@ -79,7 +71,7 @@ const englishConstants = { ENTER_OTT: 'verification code', RESEND_MAIL: 'Resend code', VERIFY: 'verify', - UNKNOWN_ERROR: 'something went wrong, please try again', + UNKNOWN_ERROR: 'Something went wrong, please try again', INVALID_CODE: 'invalid verification code', EXPIRED_CODE: 'your verification code has expired', SENDING: 'sending...', @@ -132,18 +124,8 @@ const englishConstants = { }, UPLOADING_FILES: 'file upload', FILE_NOT_UPLOADED_LIST: 'the following files were not uploaded', - SUBSCRIPTION_EXPIRED: (action) => ( - <> - your subscription has expired, please a{' '} - renew - - ), - STORAGE_QUOTA_EXCEEDED: (action) => ( - <> - you have exceeded your storage quota, please{' '} - upgrade your plan - - ), + SUBSCRIPTION_EXPIRED: 'Subscription expired', + STORAGE_QUOTA_EXCEEDED: 'Storage limit exceeded', INITIAL_LOAD_DELAY_WARNING: 'the first load may take some time', USER_DOES_NOT_EXIST: 'sorry, could not find a user with that email', UPLOAD_BUTTON_TEXT: 'upload', @@ -173,7 +155,7 @@ const englishConstants = { UPLOAD_STRATEGY_COLLECTION_PER_FOLDER: 'separate albums', SESSION_EXPIRED_MESSAGE: 'your session has expired, please login again to continue', - SESSION_EXPIRED: 'session expired', + SESSION_EXPIRED: 'Session expired', SYNC_FAILED: 'failed to sync with server, please refresh this page', PASSWORD_GENERATION_FAILED: "your browser was unable to generate a strong key that meets ente's encryption standards, please try using the mobile app or another browser", @@ -789,6 +771,8 @@ const englishConstants = {

), + UPGRADE_NOW: 'Upgrade now', + RENEW_NOW: 'Renew now', }; export default englishConstants;