Streamline camera text
This commit is contained in:
parent
8efe9529e3
commit
62c1796840
14
__tests__/camera.test.ts
Normal file
14
__tests__/camera.test.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { Camera, formatCameraText } from '@/camera';
|
||||
|
||||
describe('Camera', () => {
|
||||
it('labels correctly', () => {
|
||||
const apple: Camera = { make: 'Apple', model: 'iPhone 11 Pro' };
|
||||
expect(formatCameraText(apple, true)).toBe('Apple iPhone 11 Pro');
|
||||
expect(formatCameraText(apple, false)).toBe('iPhone 11 Pro');
|
||||
const fujifilm: Camera = { make: 'Fujifilm', model: 'X-T5' };
|
||||
expect(formatCameraText(fujifilm)).toBe('Fujifilm X-T5');
|
||||
const canon: Camera = { make: 'Canon', model: 'Canon EOS 800D' };
|
||||
expect(formatCameraText(canon)).toBe('Canon EOS 800D');
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { AiFillApple } from 'react-icons/ai';
|
||||
import { pathForCamera } from '@/site/paths';
|
||||
import { IoMdCamera } from 'react-icons/io';
|
||||
import { Camera } from '.';
|
||||
import { Camera, formatCameraText } from '.';
|
||||
import EntityLink, { EntityLinkExternalProps } from '@/components/EntityLink';
|
||||
import { clsx } from 'clsx/lite';
|
||||
|
||||
@ -22,10 +22,7 @@ export default function PhotoCamera({
|
||||
|
||||
return (
|
||||
<EntityLink
|
||||
label={<>
|
||||
{!isCameraApple && <>{camera.make} </>}
|
||||
{camera.model}
|
||||
</>}
|
||||
label={formatCameraText(camera)}
|
||||
href={pathForCamera(camera)}
|
||||
icon={showAppleIcon
|
||||
? <AiFillApple
|
||||
|
||||
@ -45,9 +45,27 @@ export const cameraFromPhoto = (
|
||||
: fallback ?? CAMERA_PLACEHOLDER;
|
||||
|
||||
export const formatCameraText = (
|
||||
{ make, model }: Camera,
|
||||
{ make, model: modelRaw }: Camera,
|
||||
includeMakeApple?: boolean,
|
||||
) =>
|
||||
make === 'Apple' && !includeMakeApple
|
||||
) => {
|
||||
// Remove potential duplicate make from model
|
||||
const model = modelRaw.replace(`${make} `, '');
|
||||
return make === 'Apple' && !includeMakeApple
|
||||
? model
|
||||
: `${make} ${model}`;
|
||||
};
|
||||
|
||||
export const formatCameraModelText = (
|
||||
{ make, model: modelRaw }: Camera,
|
||||
) => {
|
||||
// Remove potential duplicate make from model
|
||||
const model = modelRaw.replace(`${make} `, '');
|
||||
const textLength = model?.length ?? 0;
|
||||
if (textLength > 0 && textLength <= 8) {
|
||||
return model;
|
||||
} else if (model?.includes('iPhone')) {
|
||||
return model.split('iPhone')[1];
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
@ -82,18 +82,18 @@ export default function PhotoLarge({
|
||||
<PhotoTags tags={tags} />}
|
||||
</div>
|
||||
{showCamera && photoHasCameraData(photo) &&
|
||||
<div className="space-y-0.5">
|
||||
<PhotoCamera
|
||||
camera={camera}
|
||||
type="text-only"
|
||||
/>
|
||||
{showSimulation && photo.filmSimulation &&
|
||||
<div className="translate-x-[-0.3rem]">
|
||||
<PhotoFilmSimulation
|
||||
simulation={photo.filmSimulation}
|
||||
/>
|
||||
</div>}
|
||||
</div>}
|
||||
<div className="space-y-0.5">
|
||||
<PhotoCamera
|
||||
camera={camera}
|
||||
type="text-only"
|
||||
/>
|
||||
{showSimulation && photo.filmSimulation &&
|
||||
<div className="translate-x-[-0.3rem]">
|
||||
<PhotoFilmSimulation
|
||||
simulation={photo.filmSimulation}
|
||||
/>
|
||||
</div>}
|
||||
</div>}
|
||||
</>)}
|
||||
{renderMiniGrid(<>
|
||||
{photoHasExifData(photo) &&
|
||||
|
||||
@ -2,7 +2,7 @@ import { Photo } from '..';
|
||||
import ImageCaption from './components/ImageCaption';
|
||||
import ImagePhotoGrid from './components/ImagePhotoGrid';
|
||||
import ImageContainer from './components/ImageContainer';
|
||||
import { Camera, cameraFromPhoto } from '@/camera';
|
||||
import { Camera, cameraFromPhoto, formatCameraText } from '@/camera';
|
||||
import { IoMdCamera } from 'react-icons/io';
|
||||
import { NextImageSize } from '@/services/next-image';
|
||||
|
||||
@ -19,7 +19,7 @@ export default function CameraImageResponse({
|
||||
height: number
|
||||
fontFamily: string
|
||||
}) {
|
||||
const { make, model } = cameraFromPhoto(photos[0], cameraProp);
|
||||
const camera = cameraFromPhoto(photos[0], cameraProp);
|
||||
return (
|
||||
<ImageContainer {...{
|
||||
width,
|
||||
@ -38,9 +38,9 @@ export default function CameraImageResponse({
|
||||
size={height * .09}
|
||||
style={{ transform: `translateY(${height * 0.002}px)` }}
|
||||
/>
|
||||
{make.toLowerCase() !== 'apple' &&
|
||||
<span style={{textTransform: 'uppercase'}}>{make}</span>}
|
||||
<span style={{textTransform: 'uppercase'}}>{model}</span>
|
||||
<span style={{textTransform: 'uppercase'}}>
|
||||
{formatCameraText(camera)}
|
||||
</span>
|
||||
</ImageCaption>
|
||||
</ImageContainer>
|
||||
);
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { Photo } from '..';
|
||||
import { formatModelShort } from '@/utility/exif';
|
||||
import { AiFillApple } from 'react-icons/ai';
|
||||
import ImageCaption from './components/ImageCaption';
|
||||
import ImagePhotoGrid from './components/ImagePhotoGrid';
|
||||
import ImageContainer from './components/ImageContainer';
|
||||
import { OG_TEXT_BOTTOM_ALIGNMENT } from '@/site/config';
|
||||
import { NextImageSize } from '@/services/next-image';
|
||||
import { cameraFromPhoto, formatCameraModelText } from '@/camera';
|
||||
|
||||
export default function PhotoImageResponse({
|
||||
photo,
|
||||
@ -18,6 +18,10 @@ export default function PhotoImageResponse({
|
||||
height: number
|
||||
fontFamily: string
|
||||
}) {
|
||||
const model = photo.model
|
||||
? formatCameraModelText(cameraFromPhoto(photo))
|
||||
: undefined;
|
||||
|
||||
return (
|
||||
<ImageContainer {...{ width, height }}>
|
||||
<ImagePhotoGrid {...{
|
||||
@ -31,9 +35,10 @@ export default function PhotoImageResponse({
|
||||
<div style={{ display: 'flex' }}>
|
||||
<AiFillApple />
|
||||
</div>}
|
||||
<div style={{ display: 'flex' }}>
|
||||
{formatModelShort(photo.model)}
|
||||
</div>
|
||||
{model &&
|
||||
<div style={{ display: 'flex' }}>
|
||||
{model}
|
||||
</div>}
|
||||
<div style={{ display: 'flex' }}>
|
||||
{photo.focalLengthFormatted}
|
||||
</div>
|
||||
|
||||
@ -57,14 +57,3 @@ export const formatExposureCompensation = (exposureCompensation?: number) => {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
export const formatModelShort = (model?: string) => {
|
||||
const textLength = model?.length ?? 0;
|
||||
if (textLength > 0 && textLength <= 8) {
|
||||
return model;
|
||||
} else if (model?.includes('iPhone')) {
|
||||
return model.split('iPhone')[1];
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user