Merge pull request #314 from ente-io/master

release
This commit is contained in:
Abhinav Kumar 2022-01-27 15:53:20 +05:30 committed by GitHub
commit aa305cc8d9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 229 additions and 168 deletions

View file

@ -26,8 +26,6 @@ module.exports = {
'base-uri ': "'self'",
'frame-ancestors': " 'none'",
'form-action': "'none'",
'report-uri': 'https://csp-reporter.ente.io',
'report-to': 'https://csp-reporter.ente.io',
},
WORKBOX_CONFIG: {

View file

@ -1,5 +1,5 @@
import * as Sentry from '@sentry/nextjs';
import { getSentryTunnelUrl } from 'utils/common/apiUtil';
import { getSentryTunnelURL } from 'utils/common/apiUtil';
import { getUserAnonymizedID } from 'utils/user';
import {
getSentryDSN,
@ -21,7 +21,7 @@ Sentry.init({
release: SENTRY_RELEASE,
attachStacktrace: true,
autoSessionTracking: false,
tunnel: getSentryTunnelUrl(),
tunnel: getSentryTunnelURL(),
// ...
// Note: if you want to override the automatic release value, do not set a
// `release` value here - use the environment variable `SENTRY_RELEASE`, so

View file

@ -209,7 +209,7 @@ const PhotoFrame = ({
});
}, [files, deleted, search, activeCollection]);
const updateUrl = (index: number) => (url: string) => {
const updateURL = (index: number) => (url: string) => {
files[index] = {
...files[index],
msrc: url,
@ -240,7 +240,7 @@ const PhotoFrame = ({
setFiles(files);
};
const updateSrcUrl = async (index: number, url: string) => {
const updateSrcURL = async (index: number, url: string) => {
files[index] = {
...files[index],
w: window.innerWidth,
@ -337,7 +337,7 @@ const PhotoFrame = ({
selected[file[index].id] ?? false
}`}
file={file[index]}
updateUrl={updateUrl(file[index].dataIndex)}
updateURL={updateURL(file[index].dataIndex)}
onClick={onThumbnailClick(index)}
selectable={!isSharedCollection}
onSelect={handleSelect(file[index].id, index)}
@ -370,7 +370,7 @@ const PhotoFrame = ({
url = await DownloadManager.getThumbnail(item);
galleryContext.thumbs.set(item.id, url);
}
updateUrl(item.dataIndex)(url);
updateURL(item.dataIndex)(url);
item.msrc = url;
if (!item.src) {
item.src = url;
@ -397,7 +397,7 @@ const PhotoFrame = ({
url = await DownloadManager.getFile(item, true);
galleryContext.files.set(item.id, url);
}
await updateSrcUrl(item.dataIndex, url);
await updateSrcURL(item.dataIndex, url);
item.html = files[item.dataIndex].html;
item.src = files[item.dataIndex].src;
item.w = files[item.dataIndex].w;

View file

@ -91,9 +91,11 @@ const renderInfoItem = (label: string, value: string | JSX.Element) => (
);
function RenderCreationTime({
shouldDisableEdits,
file,
scheduleUpdate,
}: {
shouldDisableEdits: boolean;
file: EnteFile;
scheduleUpdate: () => void;
}) {
@ -160,7 +162,8 @@ function RenderCreationTime({
<Value
width={isInEditMode ? '20%' : '10%'}
style={{ cursor: 'pointer', marginLeft: '10px' }}>
{!isInEditMode ? (
{!shouldDisableEdits &&
(!isInEditMode ? (
<IconButton onClick={openEditMode}>
<EditIcon />
</IconButton>
@ -177,7 +180,7 @@ function RenderCreationTime({
<CloseIcon />
</IconButton>
</>
)}
))}
</Value>
</Row>
</>
@ -275,9 +278,11 @@ const FileNameEditForm = ({ filename, saveEdits, discardEdits, extension }) => {
};
function RenderFileName({
shouldDisableEdits,
file,
scheduleUpdate,
}: {
shouldDisableEdits: boolean;
file: EnteFile;
scheduleUpdate: () => void;
}) {
@ -322,13 +327,18 @@ function RenderFileName({
{getFileTitle(filename, extension)}
</FreeFlowText>
</Value>
{!shouldDisableEdits && (
<Value
width="10%"
style={{ cursor: 'pointer', marginLeft: '10px' }}>
style={{
cursor: 'pointer',
marginLeft: '10px',
}}>
<IconButton onClick={openEditMode}>
<EditIcon />
</IconButton>
</Value>
)}
</>
) : (
<FileNameEditForm
@ -396,6 +406,7 @@ function ExifData(props: { exif: any }) {
}
function InfoModal({
shouldDisableEdits,
showInfo,
handleCloseInfo,
items,
@ -419,12 +430,14 @@ function InfoModal({
)}
{metadata?.title && (
<RenderFileName
shouldDisableEdits={shouldDisableEdits}
file={items[photoSwipe?.getCurrentIndex()]}
scheduleUpdate={scheduleUpdate}
/>
)}
{metadata?.creationTime && (
<RenderCreationTime
shouldDisableEdits={shouldDisableEdits}
file={items[photoSwipe?.getCurrentIndex()]}
scheduleUpdate={scheduleUpdate}
/>
@ -744,6 +757,7 @@ function PhotoSwipe(props: Iprops) {
</div>
</div>
<InfoModal
shouldDisableEdits={props.isSharedCollection}
showInfo={showInfo}
handleCloseInfo={handleCloseInfo}
items={items}

View file

@ -39,12 +39,13 @@ function RecoveryKeyModal({ somethingWentWrong, ...props }: Props) {
return;
}
const main = async () => {
try {
const recoveryKey = await getRecoveryKey();
if (!recoveryKey) {
setRecoveryKey(bip39.entropyToMnemonic(recoveryKey));
} catch (e) {
somethingWentWrong();
props.onHide();
}
setRecoveryKey(bip39.entropyToMnemonic(recoveryKey));
};
main();
}, [props.show]);

View file

@ -238,7 +238,9 @@ export default function Sidebar(props: Props) {
onHide={() => setRecoveryModalView(false)}
somethingWentWrong={() =>
props.setDialogMessage({
title: constants.RECOVER_KEY_GENERATION_FAILED,
title: constants.ERROR,
content:
constants.RECOVER_KEY_GENERATION_FAILED,
close: { variant: 'danger' },
})
}

View file

@ -82,7 +82,7 @@ function CollectionSelector({
<CollectionCard>
<PreviewCard
file={item.file}
updateUrl={() => {}}
updateURL={() => {}}
onSelect={() => {}}
forcedEnable
/>

View file

@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react';
import React, { useContext, useEffect, useState } from 'react';
import { Form, Modal, Button } from 'react-bootstrap';
import constants from 'utils/strings/constants';
import styled, { css } from 'styled-components';
@ -21,9 +21,10 @@ import { reverseString } from 'utils/common';
import { SetDialogMessage } from 'components/MessageDialog';
import ArrowEast from 'components/icons/ArrowEast';
import LinkButton from './LinkButton';
import { DeadCenter } from 'pages/gallery';
import { DeadCenter, GalleryContext } from 'pages/gallery';
import billingService from 'services/billingService';
import { SetLoading } from 'types/gallery';
import { logError } from 'utils/sentry';
export const PlanIcon = styled.div<{ currentlySubscribed: boolean }>`
border-radius: 20px;
@ -86,6 +87,8 @@ function PlanSelector(props: Props) {
const subscription: Subscription = getUserSubscription();
const [plans, setPlans] = useState<Plan[]>(null);
const [planPeriod, setPlanPeriod] = useState<PLAN_PERIOD>(PLAN_PERIOD.YEAR);
const galleryContext = useContext(GalleryContext);
const togglePeriod = () => {
setPlanPeriod((prevPeriod) =>
prevPeriod === PLAN_PERIOD.MONTH
@ -93,9 +96,16 @@ function PlanSelector(props: Props) {
: PLAN_PERIOD.MONTH
);
};
function onReopenClick() {
galleryContext.closeMessageDialog();
galleryContext.showPlanSelectorModal();
}
useEffect(() => {
if (props.modalView) {
if (!props.modalView) {
return;
}
const main = async () => {
try {
props.setLoading(true);
let plans = await billingService.getPlans();
@ -111,10 +121,24 @@ function PlanSelector(props: Props) {
plans = [planForSubscription(subscription), ...plans];
}
setPlans(plans);
} catch (e) {
logError(e, 'plan selector modal open failed');
props.closeModal();
props.setDialogMessage({
title: constants.OPEN_PLAN_SELECTOR_MODAL_FAILED,
content: constants.UNKNOWN_ERROR,
close: { text: 'close', variant: 'danger' },
proceed: {
text: constants.REOPEN_PLAN_SELECTOR_MODAL,
variant: 'success',
action: onReopenClick,
},
});
} finally {
props.setLoading(false);
}
};
main();
}
}, [props.modalView]);
async function onPlanSelect(plan: Plan) {

View file

@ -9,7 +9,7 @@ import { GAP_BTW_TILES } from 'constants/gallery';
interface IProps {
file: EnteFile;
updateUrl: (url: string) => void;
updateURL: (url: string) => void;
onClick?: () => void;
forcedEnable?: boolean;
selectable?: boolean;
@ -161,7 +161,7 @@ export default function PreviewCard(props: IProps) {
const {
file,
onClick,
updateUrl,
updateURL,
forcedEnable,
selectable,
selected,
@ -185,7 +185,7 @@ export default function PreviewCard(props: IProps) {
if (!file.src) {
file.src = url;
}
updateUrl(url);
updateURL(url);
}
} catch (e) {
// no-op

View file

@ -129,10 +129,7 @@ const InProgressSection = (props: InProgressProps) => {
<FileList>
{fileList.map(({ fileName, progress }) => (
<li key={fileName}>
{constants.FILE_UPLOAD_PROGRESS(
fileName,
progress
)}
{`${fileName} - ${progress}%`}
</li>
))}
</FileList>
@ -235,10 +232,20 @@ export default function UploadProgress(props: Props) {
/>
<ResultSection
fileUploadResultMap={fileUploadResultMap}
fileUploadResult={FileUploadResults.SKIPPED}
fileUploadResult={FileUploadResults.ALREADY_UPLOADED}
sectionTitle={constants.SKIPPED_FILES}
sectionInfo={constants.SKIPPED_INFO}
/>
<ResultSection
fileUploadResultMap={fileUploadResultMap}
fileUploadResult={
FileUploadResults.LARGER_THAN_AVAILABLE_STORAGE
}
sectionTitle={
constants.LARGER_THAN_AVAILABLE_STORAGE_UPLOADS
}
sectionInfo={constants.LARGER_THAN_AVAILABLE_STORAGE_INFO}
/>
<ResultSection
fileUploadResultMap={fileUploadResultMap}
fileUploadResult={FileUploadResults.UNSUPPORTED}

View file

@ -30,10 +30,11 @@ export enum UPLOAD_STAGES {
}
export enum FileUploadResults {
FAILED = -1,
SKIPPED = -2,
UNSUPPORTED = -3,
BLOCKED = -4,
TOO_LARGE = -5,
UPLOADED = 100,
FAILED,
ALREADY_UPLOADED,
UNSUPPORTED,
BLOCKED,
TOO_LARGE,
LARGER_THAN_AVAILABLE_STORAGE,
UPLOADED,
}

22
src/pages/404.tsx Normal file
View file

@ -0,0 +1,22 @@
import Container from 'components/Container';
import React, { useContext, useEffect, useState } from 'react';
import constants from 'utils/strings/constants';
import { AppContext } from './_app';
export default function NotFound() {
const appContext = useContext(AppContext);
const [loading, setLoading] = useState(true);
useEffect(() => {
appContext.showNavBar(true);
setLoading(false);
}, []);
return (
<Container>
{loading ? (
<span className="sr-only">Loading...</span>
) : (
constants.NOT_FOUND
)}
</Container>
);
}

View file

@ -479,8 +479,8 @@ type AppContextType = {
sharedFiles: File[];
resetSharedFiles: () => void;
setDisappearingFlashMessage: (message: FlashMessage) => void;
redirectUrl: string;
setRedirectUrl: (url: string) => void;
redirectURL: string;
setRedirectURL: (url: string) => void;
};
export enum FLASH_MESSAGE_TYPE {
@ -510,7 +510,7 @@ export default function App({ Component, err }) {
const [sharedFiles, setSharedFiles] = useState<File[]>(null);
const [redirectName, setRedirectName] = useState<string>(null);
const [flashMessage, setFlashMessage] = useState<FlashMessage>(null);
const [redirectUrl, setRedirectUrl] = useState(null);
const [redirectURL, setRedirectURL] = useState(null);
useEffect(() => {
if (
!('serviceWorker' in navigator) ||
@ -644,8 +644,8 @@ export default function App({ Component, err }) {
sharedFiles,
resetSharedFiles,
setDisappearingFlashMessage,
redirectUrl,
setRedirectUrl,
redirectURL,
setRedirectURL,
}}>
{loading ? (
<Container>

View file

@ -76,9 +76,9 @@ export default function Credentials() {
}
await SaveKeyInSessionStore(SESSION_KEYS.ENCRYPTION_KEY, key);
await decryptAndStoreToken(key);
const redirectUrl = appContext.redirectUrl;
appContext.setRedirectUrl(null);
router.push(redirectUrl ?? PAGES.GALLERY);
const redirectURL = appContext.redirectURL;
appContext.setRedirectURL(null);
router.push(redirectURL ?? PAGES.GALLERY);
} catch (e) {
logError(e, 'user entered a wrong password');
setFieldError('passphrase', constants.INCORRECT_PASSPHRASE);

View file

@ -119,6 +119,7 @@ const defaultGalleryContext: GalleryContextType = {
thumbs: new Map(),
files: new Map(),
showPlanSelectorModal: () => null,
closeMessageDialog: () => null,
setActiveCollection: () => null,
syncWithRemote: () => null,
};
@ -144,7 +145,7 @@ export default function Gallery() {
collectionID: 0,
});
const [dialogMessage, setDialogMessage] = useState<MessageAttributes>();
const [dialogView, setDialogView] = useState(false);
const [messageDialogView, setMessageDialogView] = useState(false);
const [planModalView, setPlanModalView] = useState(false);
const [loading, setLoading] = useState(false);
const [collectionSelectorAttributes, setCollectionSelectorAttributes] =
@ -186,10 +187,13 @@ export default function Gallery() {
const [fixCreationTimeAttributes, setFixCreationTimeAttributes] =
useState<FixCreationTimeAttributes>(null);
const showPlanSelectorModal = () => setPlanModalView(true);
const closeMessageDialog = () => setMessageDialogView(false);
useEffect(() => {
const key = getKey(SESSION_KEYS.ENCRYPTION_KEY);
if (!key) {
appContext.setRedirectUrl(router.asPath);
appContext.setRedirectURL(router.asPath);
router.push(PAGES.ROOT);
return;
}
@ -218,7 +222,7 @@ export default function Gallery() {
appContext.showNavBar(true);
}, []);
useEffect(() => setDialogView(true), [dialogMessage]);
useEffect(() => setMessageDialogView(true), [dialogMessage]);
useEffect(
() => collectionSelectorAttributes && setCollectionSelectorView(true),
@ -536,7 +540,8 @@ export default function Gallery() {
<GalleryContext.Provider
value={{
...defaultGalleryContext,
showPlanSelectorModal: () => setPlanModalView(true),
showPlanSelectorModal,
closeMessageDialog,
setActiveCollection,
syncWithRemote,
}}>
@ -563,8 +568,8 @@ export default function Gallery() {
<AlertBanner bannerMessage={bannerMessage} />
<MessageDialog
size="lg"
show={dialogView}
onHide={() => setDialogView(false)}
show={messageDialogView}
onHide={closeMessageDialog}
attributes={dialogMessage}
/>
<SearchBar

View file

@ -1,4 +1,4 @@
import { getEndpoint, getPaymentsUrl } from 'utils/common/apiUtil';
import { getEndpoint, getPaymentsURL } from 'utils/common/apiUtil';
import { getToken } from 'utils/common/key';
import { setData, LS_KEYS } from 'utils/storage/localStorage';
import { convertToHumanReadable } from 'utils/billing';
@ -154,7 +154,7 @@ class billingService {
action: string
) {
try {
window.location.href = `${getPaymentsUrl()}?productID=${productID}&paymentToken=${paymentToken}&action=${action}&redirectURL=${
window.location.href = `${getPaymentsURL()}?productID=${productID}&paymentToken=${paymentToken}&action=${action}&redirectURL=${
window.location.origin
}/gallery`;
} catch (e) {

View file

@ -1,5 +1,5 @@
import { getToken } from 'utils/common/key';
import { getFileUrl, getThumbnailUrl } from 'utils/common/apiUtil';
import { getFileURL, getThumbnailURL } from 'utils/common/apiUtil';
import CryptoWorker from 'utils/crypto';
import {
generateStreamFromArrayBuffer,
@ -13,8 +13,8 @@ import { logError } from 'utils/sentry';
import { FILE_TYPE } from 'constants/file';
class DownloadManager {
private fileObjectUrlPromise = new Map<string, Promise<string>>();
private thumbnailObjectUrlPromise = new Map<number, Promise<string>>();
private fileObjectURLPromise = new Map<string, Promise<string>>();
private thumbnailObjectURLPromise = new Map<number, Promise<string>>();
public async getThumbnail(file: EnteFile) {
try {
@ -22,10 +22,18 @@ class DownloadManager {
if (!token) {
return null;
}
if (!this.thumbnailObjectUrlPromise.get(file.id)) {
if (!this.thumbnailObjectURLPromise.get(file.id)) {
const downloadPromise = async () => {
const thumbnailCache = await caches.open('thumbs');
const cacheResp: Response = await thumbnailCache.match(
const thumbnailCache = await (async () => {
try {
return await caches.open('thumbs');
} catch (e) {
return null;
// ignore
}
})();
const cacheResp: Response = await thumbnailCache?.match(
file.id.toString()
);
if (cacheResp) {
@ -34,7 +42,7 @@ class DownloadManager {
const thumb = await this.downloadThumb(token, file);
const thumbBlob = new Blob([thumb]);
try {
await thumbnailCache.put(
await thumbnailCache?.put(
file.id.toString(),
new Response(thumbBlob)
);
@ -43,12 +51,12 @@ class DownloadManager {
}
return URL.createObjectURL(thumbBlob);
};
this.thumbnailObjectUrlPromise.set(file.id, downloadPromise());
this.thumbnailObjectURLPromise.set(file.id, downloadPromise());
}
return await this.thumbnailObjectUrlPromise.get(file.id);
return await this.thumbnailObjectURLPromise.get(file.id);
} catch (e) {
this.thumbnailObjectUrlPromise.delete(file.id);
this.thumbnailObjectURLPromise.delete(file.id);
logError(e, 'get preview Failed');
throw e;
}
@ -56,7 +64,7 @@ class DownloadManager {
downloadThumb = async (token: string, file: EnteFile) => {
const resp = await HTTPService.get(
getThumbnailUrl(file.id),
getThumbnailURL(file.id),
null,
{ 'X-Auth-Token': token },
{ responseType: 'arraybuffer' }
@ -84,23 +92,23 @@ class DownloadManager {
}
return URL.createObjectURL(fileBlob);
};
if (!this.fileObjectUrlPromise.get(fileKey)) {
this.fileObjectUrlPromise.set(
if (!this.fileObjectURLPromise.get(fileKey)) {
this.fileObjectURLPromise.set(
fileKey,
getFilePromise(shouldBeConverted)
);
}
const fileURL = await this.fileObjectUrlPromise.get(fileKey);
const fileURL = await this.fileObjectURLPromise.get(fileKey);
return fileURL;
} catch (e) {
this.fileObjectUrlPromise.delete(fileKey);
this.fileObjectURLPromise.delete(fileKey);
logError(e, 'Failed to get File');
throw e;
}
};
public async getCachedOriginalFile(file: EnteFile) {
return await this.fileObjectUrlPromise.get(file.id.toString());
return await this.fileObjectURLPromise.get(file.id.toString());
}
async downloadFile(file: EnteFile) {
@ -114,7 +122,7 @@ class DownloadManager {
file.metadata.fileType === FILE_TYPE.LIVE_PHOTO
) {
const resp = await HTTPService.get(
getFileUrl(file.id),
getFileURL(file.id),
null,
{ 'X-Auth-Token': token },
{ responseType: 'arraybuffer' }
@ -126,7 +134,7 @@ class DownloadManager {
);
return generateStreamFromArrayBuffer(decrypted);
}
const resp = await fetch(getFileUrl(file.id), {
const resp = await fetch(getFileURL(file.id), {
headers: {
'X-Auth-Token': token,
},

View file

@ -129,6 +129,7 @@ export const updateTrash = async (
} catch (e) {
logError(e, 'Get trash files failed');
}
return currentTrash;
};
function removeDuplicates(trash: Trash) {

View file

@ -85,11 +85,11 @@ export async function updateFileCreationDateInEXIF(
export async function convertImageToDataURL(reader: FileReader, url: string) {
const blob = await fetch(url).then((r) => r.blob());
const dataUrl = await new Promise<string>((resolve) => {
const dataURL = await new Promise<string>((resolve) => {
reader.onload = () => resolve(reader.result as string);
reader.readAsDataURL(blob);
});
return dataUrl;
return dataURL;
}
function dataURIToBlob(dataURI) {

View file

@ -1,4 +1,5 @@
import {
FileUploadResults,
RANDOM_PERCENTAGE_PROGRESS_FOR_PUT,
UPLOAD_STAGES,
} from 'constants/upload';
@ -9,7 +10,7 @@ class UIService {
private filesUploaded: number;
private totalFileCount: number;
private fileProgress: Map<string, number>;
private uploadResult: Map<string, number>;
private uploadResult: Map<string, FileUploadResults>;
private progressUpdater: ProgressUpdater;
init(progressUpdater: ProgressUpdater) {
@ -47,8 +48,8 @@ class UIService {
this.updateProgressBarUI();
}
moveFileToResultList(filename: string) {
this.uploadResult.set(filename, this.fileProgress.get(filename));
moveFileToResultList(filename: string, uploadResult: FileUploadResults) {
this.uploadResult.set(filename, uploadResult);
this.fileProgress.delete(filename);
this.updateProgressBarUI();
}

View file

@ -185,7 +185,11 @@ class UploadManager {
this.failedFiles.push(fileWithCollection);
}
UIService.moveFileToResultList(fileWithCollection.file.name);
UIService.moveFileToResultList(
fileWithCollection.file.name,
fileUploadResult
);
UploadService.reducePendingUploadCount();
}
}

View file

@ -36,6 +36,10 @@ class UploadService {
await this.preFetchUploadURLs();
}
reducePendingUploadCount() {
this.pendingUploadCount--;
}
async readFile(
worker: any,
reader: FileReader,

View file

@ -1,5 +1,4 @@
import { EnteFile } from 'types/file';
import { sleep } from 'utils/common';
import { handleUploadError, CustomError } from 'utils/error';
import { decryptFile } from 'utils/file';
import { logError } from 'utils/sentry';
@ -22,7 +21,6 @@ import {
import { FILE_TYPE } from 'constants/file';
import { FileUploadResults } from 'constants/upload';
const TwoSecondInMillSeconds = 2000;
const FIVE_GB_IN_BYTES = 5 * 1024 * 1024 * 1024;
interface UploadResponse {
fileUploadResult: FileUploadResults;
@ -46,12 +44,6 @@ export default async function uploader(
try {
if (rawFile.size >= FIVE_GB_IN_BYTES) {
UIService.setFileProgress(
rawFile.name,
FileUploadResults.TOO_LARGE
);
// wait two second before removing the file from the progress in file section
await sleep(TwoSecondInMillSeconds);
return { fileUploadResult: FileUploadResults.TOO_LARGE };
}
fileTypeInfo = await getFileType(reader, rawFile);
@ -65,10 +57,7 @@ export default async function uploader(
);
if (fileAlreadyInCollection(existingFilesInCollection, metadata)) {
UIService.setFileProgress(rawFile.name, FileUploadResults.SKIPPED);
// wait two second before removing the file from the progress in file section
await sleep(TwoSecondInMillSeconds);
return { fileUploadResult: FileUploadResults.SKIPPED };
return { fileUploadResult: FileUploadResults.ALREADY_UPLOADED };
}
file = await UploadService.readFile(
@ -105,7 +94,6 @@ export default async function uploader(
const uploadedFile = await UploadHttpClient.uploadFile(uploadFile);
const decryptedFile = await decryptFile(uploadedFile, collection);
UIService.setFileProgress(rawFile.name, FileUploadResults.UPLOADED);
UIService.increaseFileUploaded();
return {
fileUploadResult: FileUploadResults.UPLOADED,
@ -118,29 +106,15 @@ export default async function uploader(
const error = handleUploadError(e);
switch (error.message) {
case CustomError.ETAG_MISSING:
UIService.setFileProgress(
rawFile.name,
FileUploadResults.BLOCKED
);
return { fileUploadResult: FileUploadResults.BLOCKED };
case CustomError.UNSUPPORTED_FILE_FORMAT:
UIService.setFileProgress(
rawFile.name,
FileUploadResults.UNSUPPORTED
);
return { fileUploadResult: FileUploadResults.UNSUPPORTED };
case CustomError.FILE_TOO_LARGE:
UIService.setFileProgress(
rawFile.name,
FileUploadResults.TOO_LARGE
);
return { fileUploadResult: FileUploadResults.TOO_LARGE };
return {
fileUploadResult:
FileUploadResults.LARGER_THAN_AVAILABLE_STORAGE,
};
default:
UIService.setFileProgress(
rawFile.name,
FileUploadResults.FAILED
);
return { fileUploadResult: FileUploadResults.FAILED };
}
} finally {

View file

@ -72,13 +72,21 @@ export const setRecoveryKey = (token: string, recoveryKey: RecoveryKey) =>
});
export const logoutUser = async () => {
try {
// ignore server logout result as logoutUser can be triggered before sign up or on token expiry
await _logout();
clearKeys();
clearData();
try {
await caches.delete('thumbs');
} catch (e) {
// ignore
}
await clearFiles();
router.push(PAGES.ROOT);
} catch (e) {
logError(e, 'logoutUser failed');
}
};
export const clearFiles = async () => {

View file

@ -26,6 +26,7 @@ export type GalleryContextType = {
thumbs: Map<number, string>;
files: Map<number, string>;
showPlanSelectorModal: () => void;
closeMessageDialog: () => void;
setActiveCollection: (collection: number) => void;
syncWithRemote: (force?: boolean, silent?: boolean) => Promise<void>;
};

View file

@ -4,7 +4,7 @@ export const getEndpoint = () => {
return endPoint;
};
export const getFileUrl = (id: number) => {
export const getFileURL = (id: number) => {
if (process.env.NEXT_PUBLIC_ENTE_ENDPOINT !== undefined) {
return (
`${process.env.NEXT_PUBLIC_ENTE_ENDPOINT}/files/download/${id}` ??
@ -14,7 +14,7 @@ export const getFileUrl = (id: number) => {
return `https://files.ente.io/?fileID=${id}`;
};
export const getThumbnailUrl = (id: number) => {
export const getThumbnailURL = (id: number) => {
if (process.env.NEXT_PUBLIC_ENTE_ENDPOINT !== undefined) {
return (
`${process.env.NEXT_PUBLIC_ENTE_ENDPOINT}/files/preview/${id}` ??
@ -24,11 +24,11 @@ export const getThumbnailUrl = (id: number) => {
return `https://thumbnails.ente.io/?fileID=${id}`;
};
export const getSentryTunnelUrl = () => {
export const getSentryTunnelURL = () => {
return `https://sentry-reporter.ente.io`;
};
export const getPaymentsUrl = () => {
export const getPaymentsURL = () => {
if (process.env.NEXT_PUBLIC_ENTE_ENDPOINT !== undefined) {
return process.env.NEXT_PUBLIC_ENTE_PAYMENT_ENDPOINT;
}

View file

@ -106,7 +106,7 @@ export const SaveKeyInSessionStore = async (
};
export const getRecoveryKey = async () => {
let recoveryKey = null;
let recoveryKey: string = null;
try {
const cryptoWorker = await new CryptoWorker();
@ -129,6 +129,7 @@ export const getRecoveryKey = async () => {
return recoveryKey;
} catch (e) {
logError(e, 'getRecoveryKey failed');
throw e;
}
};
@ -138,7 +139,7 @@ async function createNewRecoveryKey() {
const cryptoWorker = await new CryptoWorker();
const recoveryKey = await cryptoWorker.generateEncryptionKey();
const recoveryKey: string = await cryptoWorker.generateEncryptionKey();
const encryptedMasterKey: B64EncryptionResult =
await cryptoWorker.encryptToB64(masterKey, recoveryKey);
const encryptedRecoveryKey: B64EncryptionResult =

View file

@ -4,7 +4,6 @@ import localForage from 'localforage';
if (runningInBrowser()) {
localForage.config({
driver: localForage.INDEXEDDB,
name: 'ente-files',
version: 1.0,
storeName: 'files',

View file

@ -109,26 +109,6 @@ const englishConstants = {
},
UPLOADING_FILES: 'file upload',
FILE_NOT_UPLOADED_LIST: 'the following files were not uploaded',
FILE_UPLOAD_PROGRESS: (name: string, progress: number) => (
<div id={name}>
{name}
{' - '}
<span style={{ color: '#eee' }}>
{(() => {
switch (progress) {
case -1:
return 'failed';
case -2:
return 'already uploaded, skipping...';
case -3:
return 'unsupported file format, skipping....';
default:
return `${progress}%`;
}
})()}
</span>
</div>
),
SUBSCRIPTION_EXPIRED: (action) => (
<>
your subscription has expired, please a{' '}
@ -546,8 +526,11 @@ const englishConstants = {
BLOCKED_UPLOADS: 'blocked uploads',
INPROGRESS_UPLOADS: 'uploads in progress',
TOO_LARGE_UPLOADS: 'large files',
TOO_LARGE_INFO:
LARGER_THAN_AVAILABLE_STORAGE_UPLOADS: 'insufficient storage',
LARGER_THAN_AVAILABLE_STORAGE_INFO:
'these files were not uploaded as they exceed the maximum size limit for your storage plan',
TOO_LARGE_INFO:
'these files were not uploaded as they exceed our maximum file size limit',
UPLOAD_TO_COLLECTION: 'upload to album',
ARCHIVE: 'archive',
ALL: 'all',
@ -621,6 +604,9 @@ const englishConstants = {
DATE_TIME_ORIGINAL: 'EXIF:DateTimeOriginal',
DATE_TIME_DIGITIZED: 'EXIF:DateTimeDigitized',
CUSTOM_TIME: 'custom time',
REOPEN_PLAN_SELECTOR_MODAL: 're-open plans',
OPEN_PLAN_SELECTOR_MODAL_FAILED: 'failed to open plans',
NOT_FOUND: '404 not found',
};
export default englishConstants;

View file

@ -4592,9 +4592,9 @@ ms@2.1.2, ms@^2.1.1:
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
nanoid@^3.1.23:
version "3.1.25"
resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.1.25.tgz"
integrity sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q==
version "3.2.0"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.2.0.tgz#62667522da6673971cca916a6d3eff3f415ff80c"
integrity sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==
native-url@0.3.4:
version "0.3.4"