add support to show conversion failed message

This commit is contained in:
Abhinav 2023-06-05 22:55:02 +05:30
parent 4e7bd830f1
commit 67eabd5d02
5 changed files with 119 additions and 48 deletions

View file

@ -80,6 +80,7 @@ const PhotoFrame = ({
const [isShiftKeyPressed, setIsShiftKeyPressed] = useState(false);
const router = useRouter();
const [isSourceLoaded, setIsSourceLoaded] = useState(false);
const [conversionFailed, setConversionFailed] = useState(false);
const displayFiles = useMemoSingleThreaded(() => {
return files.map((item) => {
@ -196,7 +197,8 @@ const PhotoFrame = ({
const updateSrcURL = async (
index: number,
id: number,
mergedSrcURL: MergedSourceURL
mergedSrcURL: MergedSourceURL,
conversionFailed: boolean
) => {
const file = displayFiles[index];
// this is to prevent outdate updateSrcURL call from updating the wrong file
@ -217,6 +219,21 @@ const PhotoFrame = ({
'PhotoSwipe updateSrcURL called when source already loaded'
);
return;
} else if (file.conversionFailed) {
addLogLine(
`PhotoSwipe: updateSrcURL: conversion failed: ${file.id}`
);
logError(
new Error(
`PhotoSwipe: updateSrcURL: conversion failed: ${file.id}`
),
'PhotoSwipe updateSrcURL called when conversion failed'
);
return;
}
if (conversionFailed) {
setConversionFailed(true);
return;
}
await updateFileSrcProps(file, mergedSrcURL);
setIsSourceLoaded(true);
@ -406,18 +423,28 @@ const PhotoFrame = ({
logError(e, 'getSlideData failed get msrc url failed');
}
}
if (item.isSourceLoaded) {
setIsSourceLoaded(true);
addLogLine(`[${item.id}] source already loaded`);
return;
}
if (item.conversionFailed) {
setConversionFailed(true);
addLogLine(`[${item.id}] conversion failed`);
return;
}
if (fetching[item.id]) {
addLogLine(`[${item.id}] file download already in progress`);
return;
}
setIsSourceLoaded(false);
setConversionFailed(false);
try {
addLogLine(`[${item.id}] new file src request`);
fetching[item.id] = true;
let srcURL: MergedSourceURL;
let conversionFailed: boolean = false;
if (galleryContext.files.has(item.id)) {
addLogLine(
`[${item.id}] gallery context cache hit, using cached file`
@ -428,7 +455,10 @@ const PhotoFrame = ({
`[${item.id}] gallery context cache miss, calling downloadManager to get file`
);
appContext.startLoading();
let downloadedURL;
let downloadedURL: {
original: string[];
converted: string[];
};
if (publicCollectionGalleryContext.accessedThroughSharedURL) {
downloadedURL =
await PublicCollectionDownloadManager.getFile(
@ -441,15 +471,21 @@ const PhotoFrame = ({
downloadedURL = await DownloadManager.getFile(item, true);
}
appContext.finishLoading();
const mergedURL: MergedSourceURL = {
original: downloadedURL.original.join(','),
converted: downloadedURL.converted.join(','),
};
galleryContext.files.set(item.id, mergedURL);
srcURL = mergedURL;
if (
downloadedURL.converted.filter((url) => !!url).length !==
downloadedURL.converted.length
) {
conversionFailed = true;
} else {
const mergedURL: MergedSourceURL = {
original: downloadedURL.original.join(','),
converted: downloadedURL.converted.join(','),
};
galleryContext.files.set(item.id, mergedURL);
srcURL = mergedURL;
}
}
setIsSourceLoaded(false);
await updateSrcURL(index, item.id, srcURL);
await updateSrcURL(index, item.id, srcURL, conversionFailed);
try {
addLogLine(
@ -498,6 +534,7 @@ const PhotoFrame = ({
isHiddenCollection={activeCollection === HIDDEN_SECTION}
enableDownload={enableDownload}
isSourceLoaded={isSourceLoaded}
conversionFailed={conversionFailed}
fileToCollectionsMap={fileToCollectionsMap}
collectionNameMap={collectionNameMap}
/>

View file

@ -42,6 +42,7 @@ import ChevronLeft from '@mui/icons-material/ChevronLeft';
import { t } from 'i18next';
import { getParsedExifData } from 'services/upload/exifService';
import { getFileType } from 'services/typeDetectionService';
import { ConversionFailedBtn } from './styledComponents/ConversionFailedBtn';
interface PhotoswipeFullscreenAPI {
enter: () => void;
@ -75,6 +76,7 @@ interface Iprops {
isHiddenCollection: boolean;
enableDownload: boolean;
isSourceLoaded: boolean;
conversionFailed: boolean;
fileToCollectionsMap: Map<number, number[]>;
collectionNameMap: Map<number, string>;
}
@ -84,7 +86,7 @@ function PhotoViewer(props: Iprops) {
const [photoSwipe, setPhotoSwipe] =
useState<Photoswipe<Photoswipe.Options>>();
const { isOpen, items, isSourceLoaded } = props;
const { isOpen, items, isSourceLoaded, conversionFailed } = props;
const [isFav, setIsFav] = useState(false);
const [showInfo, setShowInfo] = useState(false);
const [exif, setExif] =
@ -559,6 +561,16 @@ function PhotoViewer(props: Iprops) {
{livePhotoBtnHTML} {t('LIVE')}
</LivePhotoBtn>
)}
{conversionFailed && (
<ConversionFailedBtn
onClick={() =>
downloadFileHelper(photoSwipe.currItem)
}>
{' '}
DOWNLOAD{' '}
</ConversionFailedBtn>
)}
<div className="pswp__container">
<div className="pswp__item" />
<div className="pswp__item" />

View file

@ -0,0 +1,15 @@
import { styled } from '@mui/material';
export const ConversionFailedBtn = styled('button')`
position: absolute;
bottom: 6vh;
left: 6vh;
height: 40px;
width: 80px;
background: #d7d7d7;
outline: none;
border: none;
border-radius: 10%;
z-index: 10;
cursor: ${(props) => (props.disabled ? 'not-allowed' : 'pointer')};
}
`;

View file

@ -60,6 +60,7 @@ export interface EnteFile
originalVideoURL?: string;
originalImageURL?: string;
dataIndex?: number;
conversionFailed?: boolean;
}
export interface TrashRequest {

View file

@ -286,14 +286,18 @@ export async function getRenderableFileURL(file: EnteFile, fileBlob: Blob) {
fileBlob
);
return {
converted: [URL.createObjectURL(convertedBlob)],
converted: [
convertedBlob ? URL.createObjectURL(convertedBlob) : null,
],
original: [URL.createObjectURL(fileBlob)],
};
}
case FILE_TYPE.LIVE_PHOTO: {
const livePhoto = await getRenderableLivePhoto(file, fileBlob);
return {
converted: livePhoto.map((asset) => URL.createObjectURL(asset)),
converted: livePhoto.map((asset) =>
asset ? URL.createObjectURL(asset) : null
),
original: [URL.createObjectURL(fileBlob)],
};
}
@ -330,52 +334,54 @@ async function getPlayableVideo(videoNameTitle: string, video: Uint8Array) {
}
export async function getRenderableImage(fileName: string, imageBlob: Blob) {
const tempFile = new File([imageBlob], fileName);
const { exactType } = await getFileType(tempFile);
let convertedImageBlob: Blob;
if (isRawFile(exactType)) {
try {
if (!isSupportedRawFormat(exactType)) {
throw Error(CustomError.UNSUPPORTED_RAW_FORMAT);
}
if (!isElectron()) {
throw Error(CustomError.NOT_AVAILABLE_ON_WEB);
}
addLogLine(
`RawConverter called for ${fileName}-${convertBytesToHumanReadable(
imageBlob.size
)}`
);
convertedImageBlob = await imageProcessor.convertToJPEG(
imageBlob,
fileName
);
addLogLine(`${fileName} successfully converted`);
} catch (e) {
try {
const tempFile = new File([imageBlob], fileName);
const { exactType } = await getFileType(tempFile);
let convertedImageBlob: Blob;
if (isRawFile(exactType)) {
try {
if (!isFileHEIC(exactType)) {
throw e;
if (!isSupportedRawFormat(exactType)) {
throw Error(CustomError.UNSUPPORTED_RAW_FORMAT);
}
if (!isElectron()) {
throw Error(CustomError.NOT_AVAILABLE_ON_WEB);
}
addLogLine(
`HEICConverter called for ${fileName}-${convertBytesToHumanReadable(
`RawConverter called for ${fileName}-${convertBytesToHumanReadable(
imageBlob.size
)}`
);
convertedImageBlob = await heicConversionService.convert(
imageBlob
convertedImageBlob = await imageProcessor.convertToJPEG(
imageBlob,
fileName
);
addLogLine(`${fileName} successfully converted`);
} catch (e) {
logError(e, 'get Renderable Image failed', {
fileType: exactType,
});
throw Error(CustomError.NON_PREVIEWABLE_FILE);
try {
if (!isFileHEIC(exactType)) {
throw e;
}
addLogLine(
`HEICConverter called for ${fileName}-${convertBytesToHumanReadable(
imageBlob.size
)}`
);
convertedImageBlob = await heicConversionService.convert(
imageBlob
);
addLogLine(`${fileName} successfully converted`);
} catch (e) {
throw Error(CustomError.NON_PREVIEWABLE_FILE);
}
}
return convertedImageBlob;
} else {
return imageBlob;
}
return convertedImageBlob;
} else {
return imageBlob;
} catch (e) {
logError(e, 'get Renderable Image failed');
return null;
}
}