Merge pull request #52 from sambecker/no-blur

Blur data configuration
This commit is contained in:
Sam Becker 2024-01-28 14:04:35 -06:00 committed by GitHub
commit 77bed4821f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 61 additions and 22 deletions

View File

@ -62,7 +62,8 @@ Installation
### 6. Optional configuration
- `NEXT_PUBLIC_PRO_MODE = 1` enables higher quality image storage
- `NEXT_PUBLIC_PRO_MODE = 1` enables higher quality image storage (will result in increased storage usage)
- `NEXT_PUBLIC_BLUR_DISABLED = 1` prevents image blur data being stored and displayed (potentially useful for limiting Postgres usage)
- `NEXT_PUBLIC_GEO_PRIVACY = 1` disables collection/display of location-based data
- `NEXT_PUBLIC_IGNORE_PRIORITY_ORDER = 1` prevents `priority_order` field affecting photo order
- `NEXT_PUBLIC_PUBLIC_API = 1` enables public API available at `/api`

View File

@ -0,0 +1,22 @@
import { BLUR_ENABLED } from '@/site/config';
import clsx from 'clsx/lite';
import Image, { ImageProps } from 'next/image';
export default function ImageBlurFallback(props: ImageProps) {
return (
// eslint-disable-next-line jsx-a11y/alt-text
<Image {...{
...props,
...BLUR_ENABLED && props.blurDataURL ? {
placeholder: 'blur',
blurDataURL: props.blurDataURL,
}: {
placeholder: 'empty',
className: clsx(
props.className,
'bg-gray-100/50 dark:bg-gray-900/50',
),
},
}} />
);
}

View File

@ -1,6 +1,6 @@
import { IMAGE_LARGE_WIDTH } from '@/site';
import Image from 'next/image';
import Link from 'next/link';
import ImageBlurFallback from './ImageBlurFallback';
export default function ImageLarge({
className,
@ -16,7 +16,7 @@ export default function ImageLarge({
src: string
alt: string
aspectRatio: number
blurData: string
blurData?: string
priority?: boolean
}) {
return (
@ -24,13 +24,12 @@ export default function ImageLarge({
href={href}
className="active:brightness-75"
>
<Image {...{
<ImageBlurFallback {...{
className,
src,
alt,
priority,
blurDataURL: blurData,
placeholder: 'blur',
width: IMAGE_LARGE_WIDTH,
height: Math.round(IMAGE_LARGE_WIDTH / aspectRatio),
}} />

View File

@ -1,5 +1,5 @@
import { IMAGE_SMALL_WIDTH } from '@/site';
import Image from 'next/image';
import ImageBlurFallback from './ImageBlurFallback';
export default function ImageSmall({
className,
@ -12,10 +12,10 @@ export default function ImageSmall({
src: string
alt: string
aspectRatio: number
blurData: string
blurData?: string
}) {
return (
<Image {...{
<ImageBlurFallback {...{
className,
src,
alt,

View File

@ -1,5 +1,5 @@
import { IMAGE_TINY_WIDTH } from '@/site';
import Image from 'next/image';
import ImageBlurFallback from './ImageBlurFallback';
export default function ImageTiny({
className,
@ -15,7 +15,7 @@ export default function ImageTiny({
blurData?: string
}) {
return (
<Image {...{
<ImageBlurFallback {...{
className,
src,
alt,

View File

@ -9,7 +9,6 @@ import {
isFormValid,
} from './form';
import FieldSetWithStatus from '@/components/FieldSetWithStatus';
import NextImage from 'next/image';
import { createPhotoAction, updatePhotoAction } from './actions';
import SubmitButtonWithStatus from '@/components/SubmitButtonWithStatus';
import Link from 'next/link';
@ -22,6 +21,8 @@ import {
} from '@/utility/date';
import { toastSuccess, toastWarning } from '@/toast';
import { getDimensionsFromSize } from '@/utility/size';
import ImageBlurFallback from '@/components/ImageBlurFallback';
import { BLUR_ENABLED } from '@/site/config';
const THUMBNAIL_SIZE = 300;
@ -97,16 +98,18 @@ export default function PhotoForm({
const url = formData.url ?? '';
const updateBlurData = useCallback((blurData: string) => {
setFormData(data => ({
...data,
blurData,
}));
if (BLUR_ENABLED) {
setFormData(data => ({
...data,
blurData,
}));
}
}, []);
return (
<div className="space-y-8 max-w-[38rem]">
<div className="flex gap-2">
<NextImage
<ImageBlurFallback
alt="Upload"
src={url}
className={clsx(

View File

@ -13,7 +13,7 @@ import {
MAKE_FUJIFILM,
} from '@/vendors/fujifilm';
import { FilmSimulation } from '@/simulation';
import { GEO_PRIVACY_ENABLED } from '@/site/config';
import { BLUR_ENABLED, GEO_PRIVACY_ENABLED } from '@/site/config';
import { TAG_FAVS, doesTagsStringIncludeFavs } from '@/tag';
type VirtualFields = 'favorite';
@ -28,8 +28,8 @@ type FormMeta = {
readOnly?: boolean
validate?: (value?: string) => string | undefined
capitalize?: boolean
hide?: boolean
hideIfEmpty?: boolean
hideTemporarily?: boolean
hideBasedOnCamera?: (make?: string, mode?: string) => boolean
loadingMessage?: string
checkbox?: boolean
@ -50,7 +50,8 @@ const FORM_METADATA: Record<keyof PhotoFormData, FormMeta> = {
blurData: {
label: 'blur data',
readOnly: true,
required: true,
required: BLUR_ENABLED,
hideIfEmpty: !BLUR_ENABLED,
loadingMessage: 'Generating blur data ...',
},
url: { label: 'url', readOnly: true },
@ -70,7 +71,7 @@ const FORM_METADATA: Record<keyof PhotoFormData, FormMeta> = {
iso: { label: 'ISO' },
exposureTime: { label: 'exposure time' },
exposureCompensation: { label: 'exposure compensation' },
locationName: { label: 'location name', hideTemporarily: true },
locationName: { label: 'location name', hide: true },
latitude: { label: 'latitude' },
longitude: { label: 'longitude' },
takenAt: { label: 'taken at' },
@ -82,7 +83,7 @@ const FORM_METADATA: Record<keyof PhotoFormData, FormMeta> = {
export const FORM_METADATA_ENTRIES =
(Object.entries(FORM_METADATA) as [keyof PhotoFormData, FormMeta][])
.filter(([_, meta]) => !meta.hideTemporarily);
.filter(([_, meta]) => !meta.hide);
export const convertFormKeysToLabels = (keys: (keyof PhotoFormData)[]) =>
keys.map(key => FORM_METADATA[key].label.toUpperCase());

View File

@ -44,7 +44,7 @@ export interface PhotoDbInsert extends PhotoExif {
id: string
url: string
extension: string
blurData: string
blurData?: string
title?: string
tags?: string[]
locationName?: string

View File

@ -37,6 +37,7 @@ export default function SiteChecklistClient({
showFilmSimulations,
showExifInfo,
isProModeEnabled,
isBlurEnabled,
isGeoPrivacyEnabled,
isPriorityOrderEnabled,
isPublicApiEnabled,
@ -270,6 +271,16 @@ export default function SiteChecklistClient({
higher quality image storage:
{renderEnvVars(['NEXT_PUBLIC_PRO_MODE'])}
</ChecklistRow>
<ChecklistRow
title="Image Blur"
status={isBlurEnabled}
isPending={isPendingPage}
optional
>
Set environment variable to {'"1"'} to prevent
image blur data being stored and displayed
{renderEnvVars(['NEXT_PUBLIC_BLUR_DISABLED'])}
</ChecklistRow>
<ChecklistRow
title="Geo Privacy"
status={isGeoPrivacyEnabled}

View File

@ -82,6 +82,7 @@ export const CURRENT_STORAGE: StorageType =
// SETTINGS
export const PRO_MODE_ENABLED = process.env.NEXT_PUBLIC_PRO_MODE === '1';
export const BLUR_ENABLED = process.env.NEXT_PUBLIC_BLUR_DISABLED !== '1';
export const GEO_PRIVACY_ENABLED = process.env.NEXT_PUBLIC_GEO_PRIVACY === '1';
export const PRIORITY_ORDER_ENABLED =
process.env.NEXT_PUBLIC_IGNORE_PRIORITY_ORDER !== '1';
@ -120,6 +121,7 @@ export const CONFIG_CHECKLIST_STATUS = {
showFilmSimulations: SHOW_FILM_SIMULATIONS,
showExifInfo: SHOW_EXIF_DATA,
isProModeEnabled: PRO_MODE_ENABLED,
isBlurEnabled: BLUR_ENABLED,
isGeoPrivacyEnabled: GEO_PRIVACY_ENABLED,
isPriorityOrderEnabled: PRIORITY_ORDER_ENABLED,
isPublicApiEnabled: PUBLIC_API_ENABLED,