Refactor infinite query constants

This commit is contained in:
Sam Becker 2024-05-19 14:41:45 -05:00
parent ecc08c1cb9
commit 446d3ae963
14 changed files with 103 additions and 128 deletions

View File

@ -1,4 +1,4 @@
import { GRID_THUMBNAILS_TO_SHOW_MAX } from '@/photo'; import { INFINITE_SCROLL_GRID_PHOTO_INITIAL } from '@/photo';
import { FilmSimulation, generateMetaForFilmSimulation } from '@/simulation'; import { FilmSimulation, generateMetaForFilmSimulation } from '@/simulation';
import FilmSimulationOverview from '@/simulation/FilmSimulationOverview'; import FilmSimulationOverview from '@/simulation/FilmSimulationOverview';
import { getPhotosFilmSimulationDataCached } from '@/simulation/data'; import { getPhotosFilmSimulationDataCached } from '@/simulation/data';
@ -20,7 +20,7 @@ export async function generateMetadata({
{ count, dateRange }, { count, dateRange },
] = await getPhotosFilmSimulationDataCachedCached({ ] = await getPhotosFilmSimulationDataCachedCached({
simulation, simulation,
limit: GRID_THUMBNAILS_TO_SHOW_MAX, limit: INFINITE_SCROLL_GRID_PHOTO_INITIAL,
}); });
const { const {
@ -55,7 +55,7 @@ export default async function FilmSimulationPage({
{ count, dateRange }, { count, dateRange },
] = await getPhotosFilmSimulationDataCachedCached({ ] = await getPhotosFilmSimulationDataCachedCached({
simulation, simulation,
limit: GRID_THUMBNAILS_TO_SHOW_MAX, limit: INFINITE_SCROLL_GRID_PHOTO_INITIAL,
}); });
return ( return (

View File

@ -1,4 +1,4 @@
import { GRID_THUMBNAILS_TO_SHOW_MAX } from '@/photo'; import { INFINITE_SCROLL_GRID_PHOTO_INITIAL } from '@/photo';
import { FilmSimulation, generateMetaForFilmSimulation } from '@/simulation'; import { FilmSimulation, generateMetaForFilmSimulation } from '@/simulation';
import FilmSimulationOverview from '@/simulation/FilmSimulationOverview'; import FilmSimulationOverview from '@/simulation/FilmSimulationOverview';
import FilmSimulationShareModal from '@/simulation/FilmSimulationShareModal'; import FilmSimulationShareModal from '@/simulation/FilmSimulationShareModal';
@ -7,7 +7,10 @@ import { Metadata } from 'next/types';
import { cache } from 'react'; import { cache } from 'react';
const getPhotosFilmSimulationDataCachedCached = const getPhotosFilmSimulationDataCachedCached =
cache(getPhotosFilmSimulationDataCached); cache((simulation: FilmSimulation) => getPhotosFilmSimulationDataCached({
simulation,
limit: INFINITE_SCROLL_GRID_PHOTO_INITIAL,
}));
interface FilmSimulationProps { interface FilmSimulationProps {
params: { simulation: FilmSimulation } params: { simulation: FilmSimulation }
@ -19,10 +22,7 @@ export async function generateMetadata({
const [ const [
photos, photos,
{ count, dateRange }, { count, dateRange },
] = await getPhotosFilmSimulationDataCachedCached({ ] = await getPhotosFilmSimulationDataCachedCached(simulation);
simulation,
limit: GRID_THUMBNAILS_TO_SHOW_MAX,
});
const { const {
url, url,
@ -54,10 +54,7 @@ export default async function Share({
const [ const [
photos, photos,
{ count, dateRange }, { count, dateRange },
] = await getPhotosFilmSimulationDataCachedCached({ ] = await getPhotosFilmSimulationDataCachedCached(simulation);
simulation,
limit: GRID_THUMBNAILS_TO_SHOW_MAX,
});
return <> return <>
<FilmSimulationShareModal {...{ simulation, photos, count, dateRange }} /> <FilmSimulationShareModal {...{ simulation, photos, count, dateRange }} />

View File

@ -1,9 +1,8 @@
import { import {
INFINITE_SCROLL_INITIAL_GRID, INFINITE_SCROLL_GRID_PHOTO_INITIAL,
generateOgImageMetaForPhotos, generateOgImageMetaForPhotos,
} from '@/photo'; } from '@/photo';
import PhotosEmptyState from '@/photo/PhotosEmptyState'; import PhotosEmptyState from '@/photo/PhotosEmptyState';
import { MAX_PHOTOS_TO_SHOW_OG } from '@/image-response';
import { Metadata } from 'next/types'; import { Metadata } from 'next/types';
import PhotoGridSidebar from '@/photo/PhotoGridSidebar'; import PhotoGridSidebar from '@/photo/PhotoGridSidebar';
import { getPhotoSidebarData } from '@/photo/data'; import { getPhotoSidebarData } from '@/photo/data';
@ -14,12 +13,12 @@ import { PATH_GRID } from '@/site/paths';
export const dynamic = 'force-static'; export const dynamic = 'force-static';
const getPhotosCached = cache(getPhotos); const getPhotosCached = cache(() => getPhotos({
limit: INFINITE_SCROLL_GRID_PHOTO_INITIAL,
}));
export async function generateMetadata(): Promise<Metadata> { export async function generateMetadata(): Promise<Metadata> {
const photos = await getPhotosCached({ const photos = await getPhotosCached()
limit: MAX_PHOTOS_TO_SHOW_OG,
})
.catch(() => []); .catch(() => []);
return generateOgImageMetaForPhotos(photos); return generateOgImageMetaForPhotos(photos);
} }
@ -32,7 +31,8 @@ export default async function GridPage() {
cameras, cameras,
simulations, simulations,
] = await Promise.all([ ] = await Promise.all([
getPhotosCached({ limit: INFINITE_SCROLL_INITIAL_GRID }).catch(() => []), getPhotosCached()
.catch(() => []),
...getPhotoSidebarData(), ...getPhotoSidebarData(),
]); ]);

View File

@ -1,6 +1,6 @@
import { import {
INFINITE_SCROLL_INITIAL_GRID, INFINITE_SCROLL_GRID_PHOTO_INITIAL,
INFINITE_SCROLL_MULTIPLE_GRID, INFINITE_SCROLL_GRID_PHOTO_MULTIPLE,
} from '@/photo'; } from '@/photo';
import { getPhotosCached, getPhotosCountCached } from '@/photo/cache'; import { getPhotosCached, getPhotosCountCached } from '@/photo/cache';
import StaggeredOgPhotos from '@/photo/StaggeredOgPhotos'; import StaggeredOgPhotos from '@/photo/StaggeredOgPhotos';
@ -11,7 +11,7 @@ export default async function GridPage() {
photos, photos,
count, count,
] = await Promise.all([ ] = await Promise.all([
getPhotosCached({ limit: INFINITE_SCROLL_INITIAL_GRID }), getPhotosCached({ limit: INFINITE_SCROLL_GRID_PHOTO_INITIAL }),
getPhotosCountCached(), getPhotosCountCached(),
]); ]);
@ -22,7 +22,7 @@ export default async function GridPage() {
<div className="mt-3"> <div className="mt-3">
<StaggeredOgPhotosInfinite <StaggeredOgPhotosInfinite
initialOffset={photos.length} initialOffset={photos.length}
itemsPerPage={INFINITE_SCROLL_MULTIPLE_GRID} itemsPerPage={INFINITE_SCROLL_GRID_PHOTO_MULTIPLE}
/> />
</div>} </div>}
</> </>

View File

@ -1,5 +1,5 @@
import { import {
GRID_THUMBNAILS_TO_SHOW_MAX, RELATED_GRID_PHOTOS_TO_SHOW,
descriptionForPhoto, descriptionForPhoto,
titleForPhoto, titleForPhoto,
} from '@/photo'; } from '@/photo';
@ -34,7 +34,7 @@ export async function generateMetadata({
}:PhotoProps): Promise<Metadata> { }:PhotoProps): Promise<Metadata> {
const { photo } = await getPhotosNearIdCachedCached( const { photo } = await getPhotosNearIdCachedCached(
photoId, photoId,
GRID_THUMBNAILS_TO_SHOW_MAX + 2, RELATED_GRID_PHOTOS_TO_SHOW + 2,
); );
if (!photo) { return {}; } if (!photo) { return {}; }
@ -68,7 +68,7 @@ export default async function PhotoPage({
}: PhotoProps & { children: React.ReactNode }) { }: PhotoProps & { children: React.ReactNode }) {
const { photos, photo } = await getPhotosNearIdCachedCached( const { photos, photo } = await getPhotosNearIdCachedCached(
photoId, photoId,
GRID_THUMBNAILS_TO_SHOW_MAX + 2, RELATED_GRID_PHOTOS_TO_SHOW + 2,
); );
if (!photo) { redirect(PATH_ROOT); } if (!photo) { redirect(PATH_ROOT); }
@ -83,8 +83,8 @@ export default async function PhotoPage({
photosGrid={photos.slice( photosGrid={photos.slice(
isPhotoFirst ? 1 : 2, isPhotoFirst ? 1 : 2,
isPhotoFirst isPhotoFirst
? GRID_THUMBNAILS_TO_SHOW_MAX + 1 ? RELATED_GRID_PHOTOS_TO_SHOW + 1
: GRID_THUMBNAILS_TO_SHOW_MAX + 2, : RELATED_GRID_PHOTOS_TO_SHOW + 2,
)} )}
/> />
</>; </>;

View File

@ -1,5 +1,4 @@
import { GRID_THUMBNAILS_TO_SHOW_MAX } from '@/photo'; import { getPhotoCached } from '@/photo/cache';
import { getPhotosNearIdCachedCached } from '@/photo/cache';
import PhotoShareModal from '@/photo/PhotoShareModal'; import PhotoShareModal from '@/photo/PhotoShareModal';
import { PATH_ROOT } from '@/site/paths'; import { PATH_ROOT } from '@/site/paths';
import { redirect } from 'next/navigation'; import { redirect } from 'next/navigation';
@ -9,12 +8,7 @@ export default async function Share({
}: { }: {
params: { photoId: string } params: { photoId: string }
}) { }) {
const { photo } = await getPhotosNearIdCachedCached( const photo = await getPhotoCached(photoId);
photoId,
// Matching common query from photo detail page
// in order to reuse cached results
GRID_THUMBNAILS_TO_SHOW_MAX + 2,
);
if (!photo) { return redirect(PATH_ROOT); } if (!photo) { return redirect(PATH_ROOT); }

View File

@ -1,6 +1,6 @@
import { import {
INFINITE_SCROLL_INITIAL_HOME, INFINITE_SCROLL_LARGE_PHOTO_INITIAL,
INFINITE_SCROLL_MULTIPLE_HOME, INFINITE_SCROLL_LARGE_PHOTO_MULTIPLE,
generateOgImageMetaForPhotos, generateOgImageMetaForPhotos,
} from '@/photo'; } from '@/photo';
import PhotosEmptyState from '@/photo/PhotosEmptyState'; import PhotosEmptyState from '@/photo/PhotosEmptyState';
@ -29,7 +29,7 @@ export default async function HomePage() {
photosCount, photosCount,
] = await Promise.all([ ] = await Promise.all([
getPhotosCached({ getPhotosCached({
limit: INFINITE_SCROLL_INITIAL_HOME, limit: INFINITE_SCROLL_LARGE_PHOTO_INITIAL,
}) })
.catch(() => []), .catch(() => []),
getPhotosCount() getPhotosCount()
@ -42,8 +42,8 @@ export default async function HomePage() {
<PhotosLarge {...{ photos }} /> <PhotosLarge {...{ photos }} />
{photosCount > photos.length && {photosCount > photos.length &&
<PhotosLargeInfinite <PhotosLargeInfinite
initialOffset={INFINITE_SCROLL_INITIAL_HOME} initialOffset={INFINITE_SCROLL_LARGE_PHOTO_INITIAL}
itemsPerPage={INFINITE_SCROLL_MULTIPLE_HOME} itemsPerPage={INFINITE_SCROLL_LARGE_PHOTO_MULTIPLE}
/>} />}
</div> </div>
: <PhotosEmptyState /> : <PhotosEmptyState />

View File

@ -1,28 +1,28 @@
import { Metadata } from 'next/types'; import { Metadata } from 'next/types';
import { CameraProps, getCameraFromParams } from '@/camera'; import { CameraProps } from '@/camera';
import { generateMetaForCamera } from '@/camera/meta'; import { generateMetaForCamera } from '@/camera/meta';
import { import { INFINITE_SCROLL_GRID_PHOTO_INITIAL } from '@/photo';
GRID_THUMBNAILS_TO_SHOW_MAX,
INFINITE_SCROLL_INITIAL_GRID,
} from '@/photo';
import { getPhotosCameraDataCached } from '@/camera/data'; import { getPhotosCameraDataCached } from '@/camera/data';
import CameraOverview from '@/camera/CameraOverview'; import CameraOverview from '@/camera/CameraOverview';
import { cache } from 'react'; import { cache } from 'react';
const getPhotosCameraDataCachedCached = cache(getPhotosCameraDataCached); const getPhotosCameraDataCachedCached = cache((
make: string,
model: string,
) => getPhotosCameraDataCached(
make,
model,
INFINITE_SCROLL_GRID_PHOTO_INITIAL,
));
export async function generateMetadata({ export async function generateMetadata({
params, params: { make, model },
}: CameraProps): Promise<Metadata> { }: CameraProps): Promise<Metadata> {
const camera = getCameraFromParams(params);
const [ const [
photos, photos,
{ count, dateRange }, { count, dateRange },
] = await getPhotosCameraDataCachedCached({
camera, camera,
limit: GRID_THUMBNAILS_TO_SHOW_MAX, ] = await getPhotosCameraDataCachedCached(make, model);
});
const { const {
url, url,
@ -48,16 +48,14 @@ export async function generateMetadata({
}; };
} }
export default async function CameraPage({ params }: CameraProps) { export default async function CameraPage({
const camera = getCameraFromParams(params); params: { make, model },
}: CameraProps) {
const [ const [
photos, photos,
{ count, dateRange }, { count, dateRange },
] = await getPhotosCameraDataCachedCached({
camera, camera,
limit: INFINITE_SCROLL_INITIAL_GRID, ] = await getPhotosCameraDataCachedCached(make, model);
});
return ( return (
<CameraOverview {...{ camera, photos, count, dateRange }} /> <CameraOverview {...{ camera, photos, count, dateRange }} />

View File

@ -1,33 +1,29 @@
import { import { CameraProps } from '@/camera';
CameraProps,
cameraFromPhoto,
getCameraFromParams,
} from '@/camera';
import CameraShareModal from '@/camera/CameraShareModal'; import CameraShareModal from '@/camera/CameraShareModal';
import { generateMetaForCamera } from '@/camera/meta'; import { generateMetaForCamera } from '@/camera/meta';
import { Metadata } from 'next/types'; import { Metadata } from 'next/types';
import { import { INFINITE_SCROLL_GRID_PHOTO_INITIAL } from '@/photo';
GRID_THUMBNAILS_TO_SHOW_MAX,
INFINITE_SCROLL_INITIAL_GRID,
} from '@/photo';
import { getPhotosCameraDataCached } from '@/camera/data'; import { getPhotosCameraDataCached } from '@/camera/data';
import CameraOverview from '@/camera/CameraOverview'; import CameraOverview from '@/camera/CameraOverview';
import { cache } from 'react'; import { cache } from 'react';
const getPhotosCameraDataCachedCached = cache(getPhotosCameraDataCached); const getPhotosCameraDataCachedCached = cache((
make: string,
model: string,
) => getPhotosCameraDataCached(
make,
model,
INFINITE_SCROLL_GRID_PHOTO_INITIAL,
));
export async function generateMetadata({ export async function generateMetadata({
params, params: { make, model },
}: CameraProps): Promise<Metadata> { }: CameraProps): Promise<Metadata> {
const camera = getCameraFromParams(params);
const [ const [
photos, photos,
{ count, dateRange }, { count, dateRange },
] = await getPhotosCameraDataCachedCached({
camera, camera,
limit: GRID_THUMBNAILS_TO_SHOW_MAX, ] = await getPhotosCameraDataCachedCached(make, model);
});
const { const {
url, url,
@ -53,18 +49,12 @@ export async function generateMetadata({
}; };
} }
export default async function Share({ params }: CameraProps) { export default async function Share({ params: { make, model } }: CameraProps) {
const cameraFromParams = getCameraFromParams(params);
const [ const [
photos, photos,
{ count, dateRange }, { count, dateRange },
] = await getPhotosCameraDataCachedCached({ camera,
camera: cameraFromParams, ] = await getPhotosCameraDataCachedCached(make, model);
limit: INFINITE_SCROLL_INITIAL_GRID,
});
const camera = cameraFromPhoto(photos[0], cameraFromParams);
return <> return <>
<CameraShareModal {...{ camera, photos, count, dateRange }} /> <CameraShareModal {...{ camera, photos, count, dateRange }} />

View File

@ -1,4 +1,4 @@
import { GRID_THUMBNAILS_TO_SHOW_MAX } from '@/photo'; import { INFINITE_SCROLL_GRID_PHOTO_INITIAL } from '@/photo';
import { PATH_ROOT } from '@/site/paths'; import { PATH_ROOT } from '@/site/paths';
import { generateMetaForTag } from '@/tag'; import { generateMetaForTag } from '@/tag';
import TagOverview from '@/tag/TagOverview'; import TagOverview from '@/tag/TagOverview';
@ -7,7 +7,8 @@ import type { Metadata } from 'next';
import { redirect } from 'next/navigation'; import { redirect } from 'next/navigation';
import { cache } from 'react'; import { cache } from 'react';
const getPhotosTagDataCachedCached = cache(getPhotosTagDataCached); const getPhotosTagDataCachedCached = cache((tag: string) =>
getPhotosTagDataCached({ tag, limit: INFINITE_SCROLL_GRID_PHOTO_INITIAL}));
interface TagProps { interface TagProps {
params: { tag: string } params: { tag: string }
@ -21,10 +22,7 @@ export async function generateMetadata({
const [ const [
photos, photos,
{ count, dateRange }, { count, dateRange },
] = await getPhotosTagDataCachedCached({ ] = await getPhotosTagDataCachedCached(tag);
tag,
limit: GRID_THUMBNAILS_TO_SHOW_MAX,
});
if (photos.length === 0) { return {}; } if (photos.length === 0) { return {}; }
@ -60,10 +58,7 @@ export default async function TagPage({
const [ const [
photos, photos,
{ count, dateRange }, { count, dateRange },
] = await getPhotosTagDataCachedCached({ ] = await getPhotosTagDataCachedCached(tag);
tag,
limit: GRID_THUMBNAILS_TO_SHOW_MAX,
});
if (photos.length === 0) { redirect(PATH_ROOT); } if (photos.length === 0) { redirect(PATH_ROOT); }

View File

@ -1,4 +1,4 @@
import { GRID_THUMBNAILS_TO_SHOW_MAX } from '@/photo'; import { INFINITE_SCROLL_GRID_PHOTO_INITIAL } from '@/photo';
import { generateMetaForTag } from '@/tag'; import { generateMetaForTag } from '@/tag';
import TagOverview from '@/tag/TagOverview'; import TagOverview from '@/tag/TagOverview';
import TagShareModal from '@/tag/TagShareModal'; import TagShareModal from '@/tag/TagShareModal';
@ -6,7 +6,8 @@ import { getPhotosTagDataCached } from '@/tag/data';
import type { Metadata } from 'next'; import type { Metadata } from 'next';
import { cache } from 'react'; import { cache } from 'react';
const getPhotosTagDataCachedCached = cache(getPhotosTagDataCached); const getPhotosTagDataCachedCached = cache((tag: string) =>
getPhotosTagDataCached({ tag, limit: INFINITE_SCROLL_GRID_PHOTO_INITIAL }));
interface TagProps { interface TagProps {
params: { tag: string } params: { tag: string }
@ -20,10 +21,7 @@ export async function generateMetadata({
const [ const [
photos, photos,
{ count, dateRange }, { count, dateRange },
] = await getPhotosTagDataCachedCached({ ] = await getPhotosTagDataCachedCached(tag);
tag,
limit: GRID_THUMBNAILS_TO_SHOW_MAX,
});
const { const {
url, url,
@ -57,10 +55,7 @@ export default async function Share({
const [ const [
photos, photos,
{ count, dateRange }, { count, dateRange },
] = await getPhotosTagDataCachedCached({ ] = await getPhotosTagDataCachedCached(tag);
tag,
limit: GRID_THUMBNAILS_TO_SHOW_MAX,
});
return <> return <>
<TagShareModal {...{ tag, photos, count, dateRange }} /> <TagShareModal {...{ tag, photos, count, dateRange }} />

View File

@ -1,17 +1,22 @@
import { Camera } from '.'; import { cameraFromPhoto, getCameraFromParams } from '.';
import { import {
getPhotosCached, getPhotosCached,
getPhotosCameraMetaCached, getPhotosCameraMetaCached,
} from '@/photo/cache'; } from '@/photo/cache';
export const getPhotosCameraDataCached = ({ export const getPhotosCameraDataCached = async (
camera, make: string,
limit, model: string,
}: { limit: number,
camera: Camera, ) => {
limit?: number, const camera = getCameraFromParams({ make, model });
}) => return Promise.all([
Promise.all([
getPhotosCached({ camera, limit }), getPhotosCached({ camera, limit }),
getPhotosCameraMetaCached(camera), getPhotosCameraMetaCached(camera),
]); ])
.then(([photos, meta]) => [
photos,
meta,
cameraFromPhoto(photos[0], camera),
] as const);
};

View File

@ -1,7 +1,7 @@
'use client'; 'use client';
import { Camera } from '@/camera'; import { Camera } from '@/camera';
import { INFINITE_SCROLL_MULTIPLE_GRID } from '.'; import { INFINITE_SCROLL_GRID_PHOTO_MULTIPLE } from '.';
import InfinitePhotoScroll from './InfinitePhotoScroll'; import InfinitePhotoScroll from './InfinitePhotoScroll';
import PhotoGrid from './PhotoGrid'; import PhotoGrid from './PhotoGrid';
import { FilmSimulation } from '@/simulation'; import { FilmSimulation } from '@/simulation';
@ -25,7 +25,7 @@ export default function PhotoGridInfinite({
<InfinitePhotoScroll <InfinitePhotoScroll
cacheKey={cacheKey} cacheKey={cacheKey}
initialOffset={initialOffset} initialOffset={initialOffset}
itemsPerPage={INFINITE_SCROLL_MULTIPLE_GRID} itemsPerPage={INFINITE_SCROLL_GRID_PHOTO_MULTIPLE}
tag={tag} tag={tag}
camera={camera} camera={camera}
simulation={simulation} simulation={simulation}

View File

@ -14,21 +14,22 @@ import camelcaseKeys from 'camelcase-keys';
import { isBefore } from 'date-fns'; import { isBefore } from 'date-fns';
import type { Metadata } from 'next'; import type { Metadata } from 'next';
// ROOT PAGE // INFINITE SCROLL: LARGE PHOTOS
export const INFINITE_SCROLL_INITIAL_HOME = export const INFINITE_SCROLL_LARGE_PHOTO_INITIAL =
process.env.NODE_ENV === 'development' ? 2 : 12; process.env.NODE_ENV === 'development' ? 2 : 12;
export const INFINITE_SCROLL_MULTIPLE_HOME = export const INFINITE_SCROLL_LARGE_PHOTO_MULTIPLE =
process.env.NODE_ENV === 'development' ? 2 : 24; process.env.NODE_ENV === 'development' ? 2 : 24;
// GRID PAGE // INFINITE SCROLL: GRID PHOTOS
export const INFINITE_SCROLL_INITIAL_GRID = HIGH_DENSITY_GRID export const INFINITE_SCROLL_GRID_PHOTO_INITIAL = HIGH_DENSITY_GRID
? process.env.NODE_ENV === 'development' ? 4 : 20 ? process.env.NODE_ENV === 'development' ? 8 : 20
: process.env.NODE_ENV === 'development' ? 4 : 24; : process.env.NODE_ENV === 'development' ? 8 : 24;
export const INFINITE_SCROLL_MULTIPLE_GRID = HIGH_DENSITY_GRID export const INFINITE_SCROLL_GRID_PHOTO_MULTIPLE = HIGH_DENSITY_GRID
? process.env.NODE_ENV === 'development' ? 4 : 40 ? process.env.NODE_ENV === 'development' ? 8 : 40
: process.env.NODE_ENV === 'development' ? 4 : 48; : process.env.NODE_ENV === 'development' ? 8 : 48;
export const GRID_THUMBNAILS_TO_SHOW_MAX = 12; // Thumbnails below /p/[photoId]
export const RELATED_GRID_PHOTOS_TO_SHOW = 12;
export const ACCEPTED_PHOTO_FILE_TYPES = [ export const ACCEPTED_PHOTO_FILE_TYPES = [
'image/jpg', 'image/jpg',