Add configuration for hiding photo taken at times

This commit is contained in:
Sam Becker 2025-01-22 19:09:51 -06:00
parent 114e73583f
commit b02dc50b88
3 changed files with 160 additions and 114 deletions

View File

@ -96,31 +96,34 @@ _⚠ READ BEFORE PROCEEDING_
Application behavior can be changed by configuring the following environment variables:
#### Site meta
#### Content
- `NEXT_PUBLIC_SITE_TITLE` (seen in browser tab)
- `NEXT_PUBLIC_SITE_DESCRIPTION` (seen in nav, beneath title)
- `NEXT_PUBLIC_SITE_ABOUT` (seen in grid sidebar—accepts rich formatting tags: `<b>`, `<strong>`, `<i>`, `<em>`, `<u>`, `<br>`)
#### Site performance
#### Performance
> ⚠️ Enabling may result in increased project usage
- `NEXT_PUBLIC_STATICALLY_OPTIMIZE_PHOTOS = 1` enables static optimization for photo pages (`p/[photoId]`), i.e., renders pages at build time
- `NEXT_PUBLIC_STATICALLY_OPTIMIZE_PHOTO_OG_IMAGES = 1` enables static optimization for OG images, i.e., renders images at build time
- `NEXT_PUBLIC_STATICALLY_OPTIMIZE_PHOTO_CATEGORIES = 1` enables static optimization for photo categories (`tag/[tag]`, `shot-on/[make]/[model]`, etc.), i.e., renders pages at build time
- `NEXT_PUBLIC_PRESERVE_ORIGINAL_UPLOADS = 1` prevents photo uploads being compressed before storing
#### Site behavior
#### Display
- `NEXT_PUBLIC_HIDE_EXIF_DATA = 1` hides EXIF data in photo details and OG images (potentially useful for portfolios, which don't focus on photography)
- `NEXT_PUBLIC_HIDE_TAKEN_AT_TIME = 1` hides taken at time from photo meta
- `NEXT_PUBLIC_HIDE_SOCIAL = 1` removes X button from share modal
- `NEXT_PUBLIC_HIDE_FILM_SIMULATIONS = 1` prevents Fujifilm simulations showing up in `/grid` sidebar and CMD-K search results
- `NEXT_PUBLIC_HIDE_REPO_LINK = 1` removes footer link to repo
#### Settings
- `NEXT_PUBLIC_GRID_HOMEPAGE = 1` shows grid layout on homepage
- `NEXT_PUBLIC_DEFAULT_THEME = light | dark` sets preferred initial theme (defaults to `system` when not configured)
- `NEXT_PUBLIC_MATTE_PHOTOS = 1` constrains the size of each photo, and enables a surrounding border (potentially useful for photos with tall aspect ratios)
- `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 (⚠️ re-compresses uploaded images in order to remove GPS information)
- `NEXT_PUBLIC_HIDE_REPO_LINK = 1` removes footer link to repo
- `NEXT_PUBLIC_ALLOW_PUBLIC_DOWNLOADS = 1` enables public photo downloads for all visitors (⚠️ may result in increased bandwidth usage)
- `NEXT_PUBLIC_PUBLIC_API = 1` enables public API available at `/api`
- `NEXT_PUBLIC_IGNORE_PRIORITY_ORDER = 1` prevents `priority_order` field affecting photo order
- `NEXT_PUBLIC_HIDE_SOCIAL = 1` removes X button from share modal
- `NEXT_PUBLIC_HIDE_FILM_SIMULATIONS = 1` prevents Fujifilm simulations showing up in `/grid` sidebar and CMD-K search results
- `NEXT_PUBLIC_HIDE_EXIF_DATA = 1` hides EXIF data in photo details and OG images (potentially useful for portfolios, which don't focus on photography)
- `NEXT_PUBLIC_GRID_ASPECT_RATIO = 1.5` sets aspect ratio for grid tiles (defaults to `1`—setting to `0` removes the constraint)
- `NEXT_PUBLIC_SHOW_LARGE_THUMBNAILS = 1` ensures large thumbnails on photo grid views
- `NEXT_PUBLIC_OG_TEXT_ALIGNMENT = BOTTOM` keeps OG image text bottom aligned (default is top)

View File

@ -11,6 +11,7 @@ import {
BiCog,
BiCopy,
BiData,
BiHide,
BiLockAlt,
BiPencil,
} from 'react-icons/bi';
@ -29,7 +30,7 @@ import WarningNote from '@/components/WarningNote';
import { RiSpeedMiniLine } from 'react-icons/ri';
export default function SiteChecklistClient({
// Config checklist
// Storage
hasDatabase,
isPostgresSslEnabled,
hasVercelPostgres,
@ -40,38 +41,49 @@ export default function SiteChecklistClient({
hasAwsS3Storage,
hasMultipleStorageProviders,
currentStorage,
// Auth
hasAuthSecret,
hasAdminUser,
// Content
hasDomain,
hasTitle,
hasDescription,
hasAbout,
hasDefaultTheme,
showRepoLink,
showSocial,
showFilmSimulations,
showExifInfo,
// AI
isAiTextGenerationEnabled,
aiTextAutoGeneratedFields,
hasAiTextAutoGeneratedFields,
// Performance
isStaticallyOptimized,
arePhotosStaticallyOptimized,
arePhotoOGImagesStaticallyOptimized,
arePhotoCategoriesStaticallyOptimized,
areOriginalUploadsPreserved,
// Display
showExifInfo,
showTakenAtTimeHidden,
showSocial,
showFilmSimulations,
showRepoLink,
// Settings
isGridHomepageEnabled,
hasDefaultTheme,
defaultTheme,
arePhotosMatted,
isBlurEnabled,
isGeoPrivacyEnabled,
isPriorityOrderEnabled,
isAiTextGenerationEnabled,
aiTextAutoGeneratedFields,
hasAiTextAutoGeneratedFields,
isPublicApiEnabled,
arePublicDownloadsEnabled,
isOgTextBottomAligned,
gridAspectRatio,
hasGridAspectRatio,
gridDensity,
hasGridDensityPreference,
arePublicDownloadsEnabled,
isPublicApiEnabled,
isPriorityOrderEnabled,
isOgTextBottomAligned,
// Misc
baseUrl,
commitSha,
commitMessage,
// Connection status
databaseError,
storageError,
@ -81,9 +93,6 @@ export default function SiteChecklistClient({
simplifiedView,
isTestingConnections,
secret,
baseUrl,
commitSha,
commitMessage,
}: ConfigChecklistStatus &
Partial<Awaited<ReturnType<typeof testConnectionsAction>>> & {
simplifiedView?: boolean
@ -473,6 +482,57 @@ export default function SiteChecklistClient({
{renderEnvVars(['NEXT_PUBLIC_PRESERVE_ORIGINAL_UPLOADS'])}
</ChecklistRow>
</Checklist>
<Checklist
title="Display"
icon={<BiHide size={18} />}
optional
>
<ChecklistRow
title="Show EXIF data"
status={showExifInfo}
optional
>
Set environment variable to {'"1"'} to hide EXIF data:
{renderEnvVars(['NEXT_PUBLIC_HIDE_EXIF_DATA'])}
</ChecklistRow>
<ChecklistRow
title="Show taken at time"
status={showTakenAtTimeHidden}
optional
>
Set environment variable to {'"1"'} to hide
taken at time from photo meta:
{renderEnvVars(['NEXT_PUBLIC_HIDE_TAKEN_AT_TIME'])}
</ChecklistRow>
<ChecklistRow
title="Show social"
status={showSocial}
optional
>
Set environment variable to {'"1"'} to hide
{' '}
X button from share modal:
{renderEnvVars(['NEXT_PUBLIC_HIDE_SOCIAL'])}
</ChecklistRow>
<ChecklistRow
title="Show Fujifilm simulations"
status={showFilmSimulations}
optional
>
Set environment variable to {'"1"'} to prevent
simulations showing up in /grid sidebar and
CMD-K results:
{renderEnvVars(['NEXT_PUBLIC_HIDE_FILM_SIMULATIONS'])}
</ChecklistRow>
<ChecklistRow
title="Show repo link"
status={showRepoLink}
optional
>
Set environment variable to {'"1"'} to hide footer link:
{renderEnvVars(['NEXT_PUBLIC_HIDE_REPO_LINK'])}
</ChecklistRow>
</Checklist>
<Checklist
title="Settings"
icon={<BiCog size={16} />}
@ -528,12 +588,24 @@ export default function SiteChecklistClient({
{renderEnvVars(['NEXT_PUBLIC_GEO_PRIVACY'])}
</ChecklistRow>
<ChecklistRow
title="Show repo link"
status={showRepoLink}
title={`Grid aspect ratio: ${gridAspectRatio}`}
status={hasGridAspectRatio}
optional
>
Set environment variable to {'"1"'} to hide footer link:
{renderEnvVars(['NEXT_PUBLIC_HIDE_REPO_LINK'])}
Set environment variable to any number to enforce aspect ratio
{' '}
(default is {'"1"'}, i.e., square)set to {'"0"'} to disable:
{renderEnvVars(['NEXT_PUBLIC_GRID_ASPECT_RATIO'])}
</ChecklistRow>
<ChecklistRow
title={`Grid density: ${gridDensity ? 'low' : 'high'}`}
status={hasGridDensityPreference}
optional
>
Set environment variable to {'"1"'} to ensure large thumbnails
on photo grid views (if not configured, density is based on
aspect ratio configuration):
{renderEnvVars(['NEXT_PUBLIC_SHOW_LARGE_THUMBNAILS'])}
</ChecklistRow>
<ChecklistRow
title="Public downloads"
@ -562,54 +634,6 @@ export default function SiteChecklistClient({
priority order photo field affecting photo order:
{renderEnvVars(['NEXT_PUBLIC_IGNORE_PRIORITY_ORDER'])}
</ChecklistRow>
<ChecklistRow
title="Show social"
status={showSocial}
optional
>
Set environment variable to {'"1"'} to hide
{' '}
X button from share modal:
{renderEnvVars(['NEXT_PUBLIC_HIDE_SOCIAL'])}
</ChecklistRow>
<ChecklistRow
title="Show Fujifilm simulations"
status={showFilmSimulations}
optional
>
Set environment variable to {'"1"'} to prevent
simulations showing up in /grid sidebar and
CMD-K results:
{renderEnvVars(['NEXT_PUBLIC_HIDE_FILM_SIMULATIONS'])}
</ChecklistRow>
<ChecklistRow
title="Show EXIF data"
status={showExifInfo}
optional
>
Set environment variable to {'"1"'} to hide EXIF data:
{renderEnvVars(['NEXT_PUBLIC_HIDE_EXIF_DATA'])}
</ChecklistRow>
<ChecklistRow
title={`Grid aspect ratio: ${gridAspectRatio}`}
status={hasGridAspectRatio}
optional
>
Set environment variable to any number to enforce aspect ratio
{' '}
(default is {'"1"'}, i.e., square)set to {'"0"'} to disable:
{renderEnvVars(['NEXT_PUBLIC_GRID_ASPECT_RATIO'])}
</ChecklistRow>
<ChecklistRow
title={`Grid density: ${gridDensity ? 'low' : 'high'}`}
status={hasGridDensityPreference}
optional
>
Set environment variable to {'"1"'} to ensure large thumbnails
on photo grid views (if not configured, density is based on
aspect ratio configuration):
{renderEnvVars(['NEXT_PUBLIC_SHOW_LARGE_THUMBNAILS'])}
</ChecklistRow>
<ChecklistRow
title="Legacy OG text alignment"
status={isOgTextBottomAligned}

View File

@ -122,6 +122,13 @@ export const CURRENT_STORAGE: StorageType =
: 'vercel-blob'
);
// AI
export const AI_TEXT_GENERATION_ENABLED =
Boolean(process.env.OPENAI_SECRET_KEY);
export const AI_TEXT_AUTO_GENERATED_FIELDS = parseAiAutoGeneratedFieldsText(
process.env.AI_TEXT_AUTO_GENERATED_FIELDS);
// PERFORMANCE
export const STATICALLY_OPTIMIZED_PHOTOS =
@ -139,6 +146,19 @@ export const PRESERVE_ORIGINAL_UPLOADS =
// Legacy environment variable name
process.env.NEXT_PUBLIC_PRO_MODE === '1';
// DISPLAY
export const SHOW_EXIF_DATA =
process.env.NEXT_PUBLIC_HIDE_EXIF_DATA !== '1';
export const SHOW_TAKEN_AT_TIME =
process.env.NEXT_PUBLIC_HIDE_TAKEN_AT_TIME !== '1';
export const SHOW_SOCIAL =
process.env.NEXT_PUBLIC_HIDE_SOCIAL !== '1';
export const SHOW_FILM_SIMULATIONS =
process.env.NEXT_PUBLIC_HIDE_FILM_SIMULATIONS !== '1';
export const SHOW_REPO_LINK =
process.env.NEXT_PUBLIC_HIDE_REPO_LINK !== '1';
// SETTINGS
export const GRID_HOMEPAGE_ENABLED =
@ -155,39 +175,30 @@ 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 AI_TEXT_GENERATION_ENABLED =
Boolean(process.env.OPENAI_SECRET_KEY);
export const AI_TEXT_AUTO_GENERATED_FIELDS = parseAiAutoGeneratedFieldsText(
process.env.AI_TEXT_AUTO_GENERATED_FIELDS);
export const PRIORITY_ORDER_ENABLED =
process.env.NEXT_PUBLIC_IGNORE_PRIORITY_ORDER !== '1';
export const PUBLIC_API_ENABLED =
process.env.NEXT_PUBLIC_PUBLIC_API === '1';
export const ALLOW_PUBLIC_DOWNLOADS =
process.env.NEXT_PUBLIC_ALLOW_PUBLIC_DOWNLOADS === '1';
export const SHOW_REPO_LINK =
process.env.NEXT_PUBLIC_HIDE_REPO_LINK !== '1';
export const SHOW_SOCIAL =
process.env.NEXT_PUBLIC_HIDE_SOCIAL !== '1';
export const SHOW_FILM_SIMULATIONS =
process.env.NEXT_PUBLIC_HIDE_FILM_SIMULATIONS !== '1';
export const SHOW_EXIF_DATA =
process.env.NEXT_PUBLIC_HIDE_EXIF_DATA !== '1';
export const GRID_ASPECT_RATIO =
process.env.NEXT_PUBLIC_GRID_ASPECT_RATIO
? parseFloat(process.env.NEXT_PUBLIC_GRID_ASPECT_RATIO)
: 1;
export const OG_TEXT_BOTTOM_ALIGNMENT =
(process.env.NEXT_PUBLIC_OG_TEXT_ALIGNMENT ?? '').toUpperCase() === 'BOTTOM';
export const ADMIN_DEBUG_TOOLS_ENABLED = process.env.ADMIN_DEBUG_TOOLS === '1';
export const PREFERS_LOW_DENSITY_GRID =
process.env.NEXT_PUBLIC_SHOW_LARGE_THUMBNAILS === '1';
export const HIGH_DENSITY_GRID =
GRID_ASPECT_RATIO <= 1 &&
!PREFERS_LOW_DENSITY_GRID;
export const ALLOW_PUBLIC_DOWNLOADS =
process.env.NEXT_PUBLIC_ALLOW_PUBLIC_DOWNLOADS === '1';
export const PUBLIC_API_ENABLED =
process.env.NEXT_PUBLIC_PUBLIC_API === '1';
export const PRIORITY_ORDER_ENABLED =
process.env.NEXT_PUBLIC_IGNORE_PRIORITY_ORDER !== '1';
export const OG_TEXT_BOTTOM_ALIGNMENT =
(process.env.NEXT_PUBLIC_OG_TEXT_ALIGNMENT ?? '').toUpperCase() === 'BOTTOM';
// INTERNAL
export const ADMIN_DEBUG_TOOLS_ENABLED = process.env.ADMIN_DEBUG_TOOLS === '1';
export const CONFIG_CHECKLIST_STATUS = {
// STORAGE
hasDatabase: HAS_DATABASE,
isPostgresSslEnabled: POSTGRES_SSL_ENABLED,
hasVercelPostgres: (
@ -205,20 +216,27 @@ export const CONFIG_CHECKLIST_STATUS = {
),
hasMultipleStorageProviders: HAS_MULTIPLE_STORAGE_PROVIDERS,
currentStorage: CURRENT_STORAGE,
// AUTH
hasAuthSecret: Boolean(process.env.AUTH_SECRET),
hasAdminUser: (
Boolean(process.env.ADMIN_EMAIL) &&
Boolean(process.env.ADMIN_PASSWORD)
),
// CONTENT
hasDomain: Boolean(process.env.NEXT_PUBLIC_SITE_DOMAIN),
hasTitle: Boolean(process.env.NEXT_PUBLIC_SITE_TITLE),
hasDescription: HAS_DEFINED_SITE_DESCRIPTION,
hasAbout: Boolean(process.env.NEXT_PUBLIC_SITE_ABOUT),
hasDefaultTheme: Boolean(process.env.NEXT_PUBLIC_DEFAULT_THEME),
showRepoLink: SHOW_REPO_LINK,
showSocial: SHOW_SOCIAL,
showFilmSimulations: SHOW_FILM_SIMULATIONS,
showExifInfo: SHOW_EXIF_DATA,
// AI
isAiTextGenerationEnabled: AI_TEXT_GENERATION_ENABLED,
aiTextAutoGeneratedFields: process.env.AI_TEXT_AUTO_GENERATED_FIELDS
? AI_TEXT_AUTO_GENERATED_FIELDS.length === 0
? ['none']
: AI_TEXT_AUTO_GENERATED_FIELDS
: ['all'],
hasAiTextAutoGeneratedFields:
Boolean(process.env.AI_TEXT_AUTO_GENERATED_FIELDS),
// PERFORMANCE
isStaticallyOptimized: (
STATICALLY_OPTIMIZED_PHOTOS ||
STATICALLY_OPTIMIZED_PHOTO_OG_IMAGES ||
@ -228,28 +246,29 @@ export const CONFIG_CHECKLIST_STATUS = {
arePhotoOGImagesStaticallyOptimized: STATICALLY_OPTIMIZED_PHOTO_OG_IMAGES,
arePhotoCategoriesStaticallyOptimized: STATICALLY_OPTIMIZED_PHOTO_CATEGORIES,
areOriginalUploadsPreserved: PRESERVE_ORIGINAL_UPLOADS,
// DISPLAY
showExifInfo: SHOW_EXIF_DATA,
showTakenAtTimeHidden: SHOW_TAKEN_AT_TIME,
showSocial: SHOW_SOCIAL,
showFilmSimulations: SHOW_FILM_SIMULATIONS,
showRepoLink: SHOW_REPO_LINK,
// SETTINGS
isGridHomepageEnabled: GRID_HOMEPAGE_ENABLED,
hasDefaultTheme: Boolean(process.env.NEXT_PUBLIC_DEFAULT_THEME),
defaultTheme: DEFAULT_THEME,
arePhotosMatted: MATTE_PHOTOS,
isBlurEnabled: BLUR_ENABLED,
isGeoPrivacyEnabled: GEO_PRIVACY_ENABLED,
isAiTextGenerationEnabled: AI_TEXT_GENERATION_ENABLED,
aiTextAutoGeneratedFields: process.env.AI_TEXT_AUTO_GENERATED_FIELDS
? AI_TEXT_AUTO_GENERATED_FIELDS.length === 0
? ['none']
: AI_TEXT_AUTO_GENERATED_FIELDS
: ['all'],
hasAiTextAutoGeneratedFields:
Boolean(process.env.AI_TEXT_AUTO_GENERATED_FIELDS),
isPriorityOrderEnabled: PRIORITY_ORDER_ENABLED,
isPublicApiEnabled: PUBLIC_API_ENABLED,
arePublicDownloadsEnabled: ALLOW_PUBLIC_DOWNLOADS,
isOgTextBottomAligned: OG_TEXT_BOTTOM_ALIGNMENT,
gridAspectRatio: GRID_ASPECT_RATIO,
hasGridAspectRatio: Boolean(process.env.NEXT_PUBLIC_GRID_ASPECT_RATIO),
gridDensity: HIGH_DENSITY_GRID,
hasGridDensityPreference:
Boolean(process.env.NEXT_PUBLIC_SHOW_LARGE_THUMBNAILS),
arePublicDownloadsEnabled: ALLOW_PUBLIC_DOWNLOADS,
isPublicApiEnabled: PUBLIC_API_ENABLED,
isPriorityOrderEnabled: PRIORITY_ORDER_ENABLED,
isOgTextBottomAligned: OG_TEXT_BOTTOM_ALIGNMENT,
// MISC
baseUrl: BASE_URL,
commitSha: VERCEL_COMMIT_SHA ? VERCEL_COMMIT_SHA.slice(0, 7) : undefined,
commitMessage: VERCEL_COMMIT_MESSAGE,