From 364772e52ce3275b072bd44ddf3580ea50fb94f0 Mon Sep 17 00:00:00 2001 From: Abhinav Date: Wed, 2 Nov 2022 16:49:04 +0530 Subject: [PATCH 1/7] show caption in photoViewer --- src/components/PhotoFrame.tsx | 1 + src/components/PhotoViewer/index.tsx | 2 +- src/types/file/index.ts | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/PhotoFrame.tsx b/src/components/PhotoFrame.tsx index 2aab1ebe6..da588e654 100644 --- a/src/components/PhotoFrame.tsx +++ b/src/components/PhotoFrame.tsx @@ -118,6 +118,7 @@ const PhotoFrame = ({ dataIndex: index, w: window.innerWidth, h: window.innerHeight, + title: item.pubMagicMetadata?.data.caption, })) .filter((item) => { if ( diff --git a/src/components/PhotoViewer/index.tsx b/src/components/PhotoViewer/index.tsx index ac2e13bb7..660ff6b2a 100644 --- a/src/components/PhotoViewer/index.tsx +++ b/src/components/PhotoViewer/index.tsx @@ -469,7 +469,7 @@ function PhotoViewer(props: Iprops) {
-
+
diff --git a/src/types/file/index.ts b/src/types/file/index.ts index 1bc7a8d0a..e35505f7c 100644 --- a/src/types/file/index.ts +++ b/src/types/file/index.ts @@ -19,6 +19,7 @@ export interface FileMagicMetadata extends Omit { export interface FilePublicMagicMetadataProps { editedTime?: number; editedName?: string; + caption?: string; } export interface FilePublicMagicMetadata From de3d11d28166bc97d90ebc5984a4688330e25931 Mon Sep 17 00:00:00 2001 From: Abhinav Date: Wed, 2 Nov 2022 18:19:05 +0530 Subject: [PATCH 2/7] add caption to info screen --- .../InfoDialog/CaptionEditForm.tsx | 78 +++++++++++++++ .../PhotoViewer/InfoDialog/RenderCaption.tsx | 96 +++++++++++++++++++ .../PhotoViewer/InfoDialog/index.tsx | 11 ++- src/constants/file/index.ts | 1 + src/utils/file/index.ts | 13 +++ src/utils/strings/englishConstants.tsx | 2 + 6 files changed, 196 insertions(+), 5 deletions(-) create mode 100644 src/components/PhotoViewer/InfoDialog/CaptionEditForm.tsx create mode 100644 src/components/PhotoViewer/InfoDialog/RenderCaption.tsx diff --git a/src/components/PhotoViewer/InfoDialog/CaptionEditForm.tsx b/src/components/PhotoViewer/InfoDialog/CaptionEditForm.tsx new file mode 100644 index 000000000..bb1f4a977 --- /dev/null +++ b/src/components/PhotoViewer/InfoDialog/CaptionEditForm.tsx @@ -0,0 +1,78 @@ +import React, { useState } from 'react'; +import constants from 'utils/strings/constants'; +import { Col, Form, FormControl } from 'react-bootstrap'; +import { Value } from 'components/Container'; +import CloseIcon from '@mui/icons-material/Close'; +import TickIcon from '@mui/icons-material/Done'; +import { Formik } from 'formik'; +import * as Yup from 'yup'; +import { MAX_CAPTION_SIZE } from 'constants/file'; +import { SmallLoadingSpinner } from '../styledComponents/SmallLoadingSpinner'; +import { IconButton } from '@mui/material'; + +export interface formValues { + caption: string; +} + +export const CaptionEditForm = ({ caption, saveEdits, discardEdits }) => { + const [loading, setLoading] = useState(false); + + const onSubmit = async (values: formValues) => { + try { + setLoading(true); + await saveEdits(values.caption); + } finally { + setLoading(false); + } + }; + return ( + + initialValues={{ caption }} + validationSchema={Yup.object().shape({ + caption: Yup.string() + .required(constants.REQUIRED) + .max(MAX_CAPTION_SIZE, constants.CAPTION_CHARACTER_LIMIT), + })} + validateOnBlur={false} + onSubmit={onSubmit}> + {({ values, errors, handleChange, handleSubmit }) => ( +
+ + + + + {errors.caption} + + + + + + {loading ? ( + + ) : ( + + )} + + + + + + + +
+ )} + + ); +}; diff --git a/src/components/PhotoViewer/InfoDialog/RenderCaption.tsx b/src/components/PhotoViewer/InfoDialog/RenderCaption.tsx new file mode 100644 index 000000000..c1b4f13ef --- /dev/null +++ b/src/components/PhotoViewer/InfoDialog/RenderCaption.tsx @@ -0,0 +1,96 @@ +import React, { useState } from 'react'; +import { updateFilePublicMagicMetadata } from 'services/fileService'; +import { EnteFile } from 'types/file'; +import constants from 'utils/strings/constants'; +import { changeCaption, updateExistingFilePubMetadata } from 'utils/file'; +import EditIcon from '@mui/icons-material/Edit'; +import { FreeFlowText, Label, Row, Value } from 'components/Container'; +import { logError } from 'utils/sentry'; +import { IconButton, Typography } from '@mui/material'; +import { CaptionEditForm } from './CaptionEditForm'; + +export const getFileTitle = (filename, extension) => { + if (extension) { + return filename + '.' + extension; + } else { + return filename; + } +}; + +export function RenderCaption({ + shouldDisableEdits, + file, + scheduleUpdate, +}: { + shouldDisableEdits: boolean; + file: EnteFile; + scheduleUpdate: () => void; +}) { + const [caption, setCaption] = useState( + file?.pubMagicMetadata?.data.caption + ); + const [isInEditMode, setIsInEditMode] = useState(false); + const openEditMode = () => setIsInEditMode(true); + const closeEditMode = () => setIsInEditMode(false); + + const saveEdits = async (newCaption: string) => { + try { + if (file) { + if (caption === newCaption) { + closeEditMode(); + return; + } + setCaption(newCaption); + + let updatedFile = await changeCaption(file, newCaption); + updatedFile = ( + await updateFilePublicMagicMetadata([updatedFile]) + )[0]; + updateExistingFilePubMetadata(file, updatedFile); + scheduleUpdate(); + } + } catch (e) { + logError(e, 'failed to update caption'); + } finally { + closeEditMode(); + } + }; + return ( + <> + + + {!isInEditMode ? ( + <> + + {caption ? ( + {caption} + ) : ( + + Add a caption + + )} + + {!shouldDisableEdits && ( + + + + + + )} + + ) : ( + + )} + + + ); +} diff --git a/src/components/PhotoViewer/InfoDialog/index.tsx b/src/components/PhotoViewer/InfoDialog/index.tsx index 133390b86..248d9e410 100644 --- a/src/components/PhotoViewer/InfoDialog/index.tsx +++ b/src/components/PhotoViewer/InfoDialog/index.tsx @@ -11,6 +11,7 @@ import { AppContext } from 'pages/_app'; import { Location, Metadata } from 'types/upload'; import Photoswipe from 'photoswipe'; import { getEXIFLocation } from 'services/upload/exifService'; +import { RenderCaption } from './RenderCaption'; const FileInfoDialog = styled(Dialog)(({ theme }) => ({ zIndex: 1501, @@ -78,11 +79,11 @@ export function FileInfo({ {constants.METADATA} - - {RenderInfoItem( - constants.FILE_ID, - items[photoSwipe?.getCurrentIndex()]?.id - )} + {metadata?.title && ( File time updation failed for some files, please retry ), FILE_NAME_CHARACTER_LIMIT: '100 characters max', + CAPTION_CHARACTER_LIMIT: '280 characters max', DATE_TIME_ORIGINAL: 'EXIF:DateTimeOriginal', DATE_TIME_DIGITIZED: 'EXIF:DateTimeDigitized', From b6628a087cb178779bd71799eec235cae055bda7 Mon Sep 17 00:00:00 2001 From: Abhinav Date: Wed, 2 Nov 2022 18:59:37 +0530 Subject: [PATCH 3/7] add title to enteFile type --- src/types/file/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/types/file/index.ts b/src/types/file/index.ts index e35505f7c..9b48f4448 100644 --- a/src/types/file/index.ts +++ b/src/types/file/index.ts @@ -44,6 +44,7 @@ export interface EnteFile { html: string; w: number; h: number; + title: string; isDeleted: boolean; isTrashed?: boolean; deleteBy?: number; From 95a8750351a654e7fd001a920a44cb9bccf54a88 Mon Sep 17 00:00:00 2001 From: Abhinav Date: Wed, 2 Nov 2022 19:08:45 +0530 Subject: [PATCH 4/7] fix navigation button click triggering causing double skip --- src/components/PhotoViewer/index.tsx | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/components/PhotoViewer/index.tsx b/src/components/PhotoViewer/index.tsx index 660ff6b2a..42bd9b573 100644 --- a/src/components/PhotoViewer/index.tsx +++ b/src/components/PhotoViewer/index.tsx @@ -33,6 +33,7 @@ import ChevronRight from '@mui/icons-material/ChevronRight'; import DeleteIcon from '@mui/icons-material/Delete'; import { trashFiles } from 'services/fileService'; import { getTrashFileMessage } from 'utils/ui'; +import { ChevronLeft } from '@mui/icons-material'; interface Iprops { isOpen: boolean; @@ -456,17 +457,13 @@ function PhotoViewer(props: Iprops) {
From daea01a6e9d8c592b684bc28374dec057fbdadac Mon Sep 17 00:00:00 2001 From: Abhinav Date: Wed, 2 Nov 2022 19:18:28 +0530 Subject: [PATCH 5/7] refresh the photoswipe view with updated caption --- src/components/PhotoViewer/InfoDialog/RenderCaption.tsx | 4 ++++ src/components/PhotoViewer/InfoDialog/index.tsx | 3 +++ src/components/PhotoViewer/index.tsx | 8 ++++++++ 3 files changed, 15 insertions(+) diff --git a/src/components/PhotoViewer/InfoDialog/RenderCaption.tsx b/src/components/PhotoViewer/InfoDialog/RenderCaption.tsx index c1b4f13ef..d6d1b210d 100644 --- a/src/components/PhotoViewer/InfoDialog/RenderCaption.tsx +++ b/src/components/PhotoViewer/InfoDialog/RenderCaption.tsx @@ -21,10 +21,12 @@ export function RenderCaption({ shouldDisableEdits, file, scheduleUpdate, + refreshPhotoswipe, }: { shouldDisableEdits: boolean; file: EnteFile; scheduleUpdate: () => void; + refreshPhotoswipe: () => void; }) { const [caption, setCaption] = useState( file?.pubMagicMetadata?.data.caption @@ -47,6 +49,8 @@ export function RenderCaption({ await updateFilePublicMagicMetadata([updatedFile]) )[0]; updateExistingFilePubMetadata(file, updatedFile); + file.title = file.pubMagicMetadata.data.caption; + refreshPhotoswipe(); scheduleUpdate(); } } catch (e) { diff --git a/src/components/PhotoViewer/InfoDialog/index.tsx b/src/components/PhotoViewer/InfoDialog/index.tsx index 248d9e410..642d0d76b 100644 --- a/src/components/PhotoViewer/InfoDialog/index.tsx +++ b/src/components/PhotoViewer/InfoDialog/index.tsx @@ -32,6 +32,7 @@ interface Iprops { metadata: Metadata; exif: any; scheduleUpdate: () => void; + refreshPhotoswipe: () => void; } export function FileInfo({ @@ -43,6 +44,7 @@ export function FileInfo({ metadata, exif, scheduleUpdate, + refreshPhotoswipe, }: Iprops) { const appContext = useContext(AppContext); const [location, setLocation] = useState(null); @@ -83,6 +85,7 @@ export function FileInfo({ shouldDisableEdits={shouldDisableEdits} file={items[photoSwipe?.getCurrentIndex()]} scheduleUpdate={scheduleUpdate} + refreshPhotoswipe={refreshPhotoswipe} /> {metadata?.title && ( { + photoSwipe.invalidateCurrItems(); + if (isOpen) { + photoSwipe.updateSize(true); + } + }; + const checkExifAvailable = async () => { setExif(null); await sleep(100); @@ -480,6 +487,7 @@ function PhotoViewer(props: Iprops) { metadata={metadata} exif={exif} scheduleUpdate={scheduleUpdate} + refreshPhotoswipe={refreshPhotoswipe} /> ); From a26f6ec50d1610731f10742eb1d9817d26de88d9 Mon Sep 17 00:00:00 2001 From: Abhinav Date: Wed, 2 Nov 2022 19:55:22 +0530 Subject: [PATCH 6/7] style caption nicely --- src/components/PhotoViewer/index.tsx | 4 ++-- src/styles/global.css | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/components/PhotoViewer/index.tsx b/src/components/PhotoViewer/index.tsx index b91a9b298..d725dd9aa 100644 --- a/src/components/PhotoViewer/index.tsx +++ b/src/components/PhotoViewer/index.tsx @@ -472,8 +472,8 @@ function PhotoViewer(props: Iprops) { title={constants.NEXT}> -
-
+
+
diff --git a/src/styles/global.css b/src/styles/global.css index f2d2e6271..93005532c 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -120,6 +120,21 @@ html, body { margin-right: 20px; } +.pswp-custom-caption { + text-align: right; + width: 375px; + font-size:14px; + line-height: 17px; +} + +.pswp-custom-caption-container { + width: 100%; + display: flex; + justify-content: flex-end; + bottom: 56px; + background-color: transparent !important; + padding:16px; +} .bg-upload-progress-bar { background-color: #51cd7c; From 9d9dcf33d7e8cb07b5fadb199134a89f576b7274 Mon Sep 17 00:00:00 2001 From: Abhinav Date: Wed, 2 Nov 2022 20:00:17 +0530 Subject: [PATCH 7/7] caption not required compulsorily --- src/components/PhotoViewer/InfoDialog/CaptionEditForm.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/PhotoViewer/InfoDialog/CaptionEditForm.tsx b/src/components/PhotoViewer/InfoDialog/CaptionEditForm.tsx index bb1f4a977..4d60b34ed 100644 --- a/src/components/PhotoViewer/InfoDialog/CaptionEditForm.tsx +++ b/src/components/PhotoViewer/InfoDialog/CaptionEditForm.tsx @@ -29,9 +29,10 @@ export const CaptionEditForm = ({ caption, saveEdits, discardEdits }) => { initialValues={{ caption }} validationSchema={Yup.object().shape({ - caption: Yup.string() - .required(constants.REQUIRED) - .max(MAX_CAPTION_SIZE, constants.CAPTION_CHARACTER_LIMIT), + caption: Yup.string().max( + MAX_CAPTION_SIZE, + constants.CAPTION_CHARACTER_LIMIT + ), })} validateOnBlur={false} onSubmit={onSubmit}>