Merge branch 'main' into ppr-static

This commit is contained in:
Sam Becker 2024-04-28 11:03:17 -05:00
commit b422cc9e88
7 changed files with 38 additions and 23 deletions

View File

@ -194,6 +194,9 @@ FAQ
#### Why are my thumbnails square?
> Absent configuration, the default grid aspect ratio is `1`. It can be set to any number (for instance `1.5` for 3:2 images) via `NEXT_PUBLIC_GRID_ASPECT_RATIO` or ignored entirely by setting to `0`.
#### Why don't my photo changes show up immediately?
> This template statically optimizes core views like `/` and `/grid` to minimize visitor load times. Consequently, when photos are added, edited, or removed, it might take several minutes for those changes to propagate. If it seems like a change is not taking effect, try navigating to `/admin/configuration` and clicking "Clear Cache."
#### My images/content have fallen out of sync with my database and/or my production site no longer matches local development. What do I do?
> Navigate to `/admin/configuration` and click "Clear Cache."

View File

@ -16,7 +16,7 @@ export default async function AdminNav() {
countPhotos,
countUploads,
countTags,
mostRecentUpdate,
mostRecentPhotoUpdateTime,
] = await Promise.all([
getPhotosCountIncludingHiddenCached().catch(() => 0),
getStorageUploadUrlsNoStore()
@ -53,6 +53,6 @@ export default async function AdminNav() {
if (countTags > 0) { items.push(navItemTags); }
return (
<AdminNavClient {...{ items, mostRecentUpdate }} />
<AdminNavClient {...{ items, mostRecentPhotoUpdateTime }} />
);
}

View File

@ -12,31 +12,43 @@ import { clsx } from 'clsx/lite';
import { differenceInMinutes } from 'date-fns';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import { useMemo } from 'react';
import { useEffect, useMemo, useState } from 'react';
import { BiCog } from 'react-icons/bi';
import { FaRegClock } from 'react-icons/fa';
const RECENCY_THRESHOLD = 5;
const areTimesRecent = (dates: Date[]) => dates
.some(date => differenceInMinutes(new Date(), date) < 5);
export default function AdminNavClient({
items,
mostRecentUpdate,
mostRecentPhotoUpdateTime,
}: {
items: {
label: string,
href: string,
count: number,
}[]
mostRecentUpdate?: Date
mostRecentPhotoUpdateTime?: Date
}) {
const pathname = usePathname();
const { adminUpdates = [] } = useAppState();
const { adminUpdateTimes = [] } = useAppState();
const shouldShowBanner = useMemo(() =>
((mostRecentUpdate ? [mostRecentUpdate] : []).concat(adminUpdates))
.some(date => differenceInMinutes(new Date(), date) < RECENCY_THRESHOLD)
, [mostRecentUpdate, adminUpdates]);
const updateTimes = useMemo(() =>
(mostRecentPhotoUpdateTime ? [mostRecentPhotoUpdateTime] : [])
.concat(adminUpdateTimes)
, [mostRecentPhotoUpdateTime, adminUpdateTimes]);
const [shouldShowBanner, setShouldShowBanner] =
useState(areTimesRecent(updateTimes));
useEffect(() => {
// Check every 10 seconds if update times are recent
const timeout = setTimeout(() =>
setShouldShowBanner(areTimesRecent(updateTimes))
, 10_000);
return () => clearTimeout(timeout);
}, [updateTimes]);
return (
<SiteGrid

View File

@ -20,7 +20,7 @@ export default function AdminPhotoMenuClient({
photo: Photo
revalidatePhoto?: RevalidatePhoto
}) {
const { isUserSignedIn, addAdminUpdate } = useAppState();
const { isUserSignedIn, registerAdminUpdate } = useAppState();
const isFav = isPhotoFav(photo);
const path = usePathname();
@ -64,7 +64,7 @@ export default function AdminPhotoMenuClient({
shouldRedirectDelete,
).then(() => {
revalidatePhoto?.(photo.id, true);
addAdminUpdate?.();
registerAdminUpdate?.();
});
}
},

View File

@ -17,15 +17,15 @@ export default function DeleteButton (
...rest
} = props;
const { invalidateSwr, addAdminUpdate } = useAppState();
const { invalidateSwr, registerAdminUpdate } = useAppState();
const onFormSubmit = useCallback(() => {
onFormSubmitProps?.();
if (clearLocalState) {
invalidateSwr?.();
addAdminUpdate?.();
registerAdminUpdate?.();
}
}, [onFormSubmitProps, clearLocalState, invalidateSwr, addAdminUpdate]);
}, [onFormSubmitProps, clearLocalState, invalidateSwr, registerAdminUpdate]);
return <SubmitButtonWithStatus
{...rest}

View File

@ -16,8 +16,8 @@ export interface AppStateContext {
setShouldRespondToKeyboardCommands?: Dispatch<SetStateAction<boolean>>
isCommandKOpen?: boolean
setIsCommandKOpen?: Dispatch<SetStateAction<boolean>>
adminUpdates?: Date[]
addAdminUpdate?: () => void
adminUpdateTimes?: Date[]
registerAdminUpdate?: () => void
shouldShowBaselineGrid?: boolean
setShouldShowBaselineGrid?: Dispatch<SetStateAction<boolean>>
clearNextPhotoAnimation?: () => void

View File

@ -26,7 +26,7 @@ export default function AppStateProvider({
useState(true);
const [isCommandKOpen, setIsCommandKOpen] =
useState(false);
const [adminUpdates, setAdminUpdates] = useState<Date[]>([]);
const [adminUpdateTimes, setAdminUpdateTimes] = useState<Date[]>([]);
const [shouldShowBaselineGrid, setShouldShowBaselineGrid] =
useState(false);
@ -35,8 +35,8 @@ export default function AppStateProvider({
const { data } = useSWR('getCurrentUser', getCurrentUser);
useEffect(() => setUserEmail(data?.email ?? undefined), [data]);
const addAdminUpdate = useCallback(() =>
setAdminUpdates(updates => [...updates, new Date()])
const registerAdminUpdate = useCallback(() =>
setAdminUpdateTimes(updates => [...updates, new Date()])
, []);
useEffect(() => {
@ -60,8 +60,8 @@ export default function AppStateProvider({
setShouldRespondToKeyboardCommands,
isCommandKOpen,
setIsCommandKOpen,
adminUpdates,
addAdminUpdate,
adminUpdateTimes,
registerAdminUpdate,
shouldShowBaselineGrid,
setShouldShowBaselineGrid,
clearNextPhotoAnimation: () => setNextPhotoAnimation?.(undefined),