Add focal length to cmd-k menu

This commit is contained in:
Sam Becker 2024-06-05 20:02:30 -05:00
parent 7e51968b11
commit cf3e6c1300
4 changed files with 49 additions and 2 deletions

View File

@ -9,6 +9,11 @@ import {
absolutePathForFocalLengthImage, absolutePathForFocalLengthImage,
} from '@/site/paths'; } from '@/site/paths';
export type FocalLengths = {
focal: number
count: number
}[]
export const getFocalLengthFromString = (focalString?: string) => { export const getFocalLengthFromString = (focalString?: string) => {
const focal = focalString?.match(/^([0-9]+)mm/)?.[1]; const focal = focalString?.match(/^([0-9]+)mm/)?.[1];
return focal ? parseInt(focal, 10) : 0; return focal ? parseInt(focal, 10) : 0;

View File

@ -14,6 +14,7 @@ import {
getPhotosNearId, getPhotosNearId,
getPhotosMostRecentUpdate, getPhotosMostRecentUpdate,
getPhotosMeta, getPhotosMeta,
getUniqueFocalLengths,
} from '@/photo/db/query'; } from '@/photo/db/query';
import { GetPhotosOptions } from './db'; import { GetPhotosOptions } from './db';
import { parseCachedPhotoDates, parseCachedPhotosDates } from '@/photo'; import { parseCachedPhotoDates, parseCachedPhotosDates } from '@/photo';
@ -37,6 +38,7 @@ const KEY_PHOTO = 'photo';
const KEY_TAGS = 'tags'; const KEY_TAGS = 'tags';
const KEY_CAMERAS = 'cameras'; const KEY_CAMERAS = 'cameras';
const KEY_FILM_SIMULATIONS = 'film-simulations'; const KEY_FILM_SIMULATIONS = 'film-simulations';
const KEY_FOCAL_LENGTHS = 'focal-lengths';
// Type keys // Type keys
const KEY_COUNT = 'count'; const KEY_COUNT = 'count';
const KEY_HIDDEN = 'hidden'; const KEY_HIDDEN = 'hidden';
@ -196,6 +198,12 @@ export const getUniqueFilmSimulationsCached =
[KEY_PHOTOS, KEY_FILM_SIMULATIONS], [KEY_PHOTOS, KEY_FILM_SIMULATIONS],
); );
export const getUniqueFocalLengthsCached =
unstable_cache(
getUniqueFocalLengths,
[KEY_PHOTOS, KEY_FOCAL_LENGTHS],
);
// No store // No store
export const getPhotosNoStore = (...args: Parameters<typeof getPhotos>) => { export const getPhotosNoStore = (...args: Parameters<typeof getPhotos>) => {

View File

@ -21,6 +21,7 @@ import {
getOrderByFromOptions, getOrderByFromOptions,
} from '.'; } from '.';
import { getWheresFromOptions } from '.'; import { getWheresFromOptions } from '.';
import { FocalLengths } from '@/focal';
const createPhotosTable = () => const createPhotosTable = () =>
sql` sql`
@ -283,6 +284,20 @@ export const getUniqueFilmSimulations = async () =>
}))) })))
, 'getUniqueFilmSimulations'); , 'getUniqueFilmSimulations');
export const getUniqueFocalLengths = async () =>
safelyQueryPhotos(() => sql`
SELECT DISTINCT focal_length, COUNT(*)
FROM photos
WHERE hidden IS NOT TRUE AND focal_length IS NOT NULL
GROUP BY focal_length
ORDER BY focal_length ASC
`.then(({ rows }): FocalLengths => rows
.map(({ focal_length, count }) => ({
focal: parseInt(focal_length, 10),
count: parseInt(count, 10),
})))
, 'getUniqueFocalLengths');
export const getPhotos = async (options: GetPhotosOptions = {}) => export const getPhotos = async (options: GetPhotosOptions = {}) =>
safelyQueryPhotos(async () => { safelyQueryPhotos(async () => {
const sql = ['SELECT * FROM photos']; const sql = ['SELECT * FROM photos'];

View File

@ -10,15 +10,18 @@ import {
import { import {
pathForCamera, pathForCamera,
pathForFilmSimulation, pathForFilmSimulation,
pathForFocalLength,
} from './paths'; } from './paths';
import { formatCameraText } from '@/camera'; import { formatCameraText } from '@/camera';
import { photoQuantityText } from '@/photo'; import { photoQuantityText } from '@/photo';
import { formatCount, formatCountDescriptive } from '@/utility/string'; import { formatCount, formatCountDescriptive } from '@/utility/string';
import { TagsWithMeta } from '@/tag';
import PhotoFilmSimulationIcon from '@/simulation/PhotoFilmSimulationIcon'; import PhotoFilmSimulationIcon from '@/simulation/PhotoFilmSimulationIcon';
import { IoMdCamera } from 'react-icons/io'; import { IoMdCamera } from 'react-icons/io';
import { ADMIN_DEBUG_TOOLS_ENABLED, SHOW_FILM_SIMULATIONS } from './config'; import { ADMIN_DEBUG_TOOLS_ENABLED, SHOW_FILM_SIMULATIONS } from './config';
import { labelForFilmSimulation } from '@/vendors/fujifilm'; import { labelForFilmSimulation } from '@/vendors/fujifilm';
import { getUniqueFocalLengths } from '@/photo/db/query';
import { formatFocalLength } from '@/focal';
import { TbCone } from 'react-icons/tb';
export default async function CommandK() { export default async function CommandK() {
const [ const [
@ -26,15 +29,17 @@ export default async function CommandK() {
tags, tags,
cameras, cameras,
filmSimulations, filmSimulations,
focalLengths,
] = await Promise.all([ ] = await Promise.all([
getPhotosMetaCached() getPhotosMetaCached()
.then(({ count }) => count) .then(({ count }) => count)
.catch(() => 0), .catch(() => 0),
getUniqueTagsCached().catch(() => [] as TagsWithMeta), getUniqueTagsCached().catch(() => []),
getUniqueCamerasCached().catch(() => []), getUniqueCamerasCached().catch(() => []),
SHOW_FILM_SIMULATIONS SHOW_FILM_SIMULATIONS
? getUniqueFilmSimulationsCached().catch(() => []) ? getUniqueFilmSimulationsCached().catch(() => [])
: [], : [],
getUniqueFocalLengths().catch(() => []),
]); ]);
const SECTION_CAMERAS: CommandKSection = { const SECTION_CAMERAS: CommandKSection = {
@ -61,11 +66,25 @@ export default async function CommandK() {
})), })),
}; };
const SECTION_FOCAL: CommandKSection = {
heading: 'Focal Lengths',
accessory: <TbCone
className="rotate-[270deg] text-[14px]"
/>,
items: focalLengths.map(({ focal, count }) => ({
label: formatFocalLength(focal)!,
annotation: formatCount(count),
annotationAria: formatCountDescriptive(count),
path: pathForFocalLength(focal),
})),
};
return <CommandKClient return <CommandKClient
tags={tags} tags={tags}
serverSections={[ serverSections={[
SECTION_CAMERAS, SECTION_CAMERAS,
SECTION_FILM, SECTION_FILM,
SECTION_FOCAL,
]} ]}
showDebugTools={ADMIN_DEBUG_TOOLS_ENABLED} showDebugTools={ADMIN_DEBUG_TOOLS_ENABLED}
footer={photoQuantityText(count, false)} footer={photoQuantityText(count, false)}