Compare commits
6 Commits
main
...
recent-images
| Author | SHA1 | Date | |
|---|---|---|---|
| 534ee35451 | |||
| fa50031f0a | |||
| 1f9fa7b204 | |||
| 496185cc88 | |||
| e046649be1 | |||
| 6214944649 |
@@ -0,0 +1,2 @@
|
|||||||
|
[lfs]
|
||||||
|
url = "https://git.chuckdries.com/chuckdries/Personal-Website.git/info/lfs/"
|
||||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
+15
-2
@@ -10,6 +10,10 @@ import sharp from "sharp";
|
|||||||
import { Palette } from "node-vibrant/lib/color";
|
import { Palette } from "node-vibrant/lib/color";
|
||||||
import { performance } from "perf_hooks";
|
import { performance } from "perf_hooks";
|
||||||
|
|
||||||
|
import util from 'node:util';
|
||||||
|
import { exec as _exec } from "child_process";
|
||||||
|
const exec = util.promisify(_exec)
|
||||||
|
|
||||||
// const path = require("path");
|
// const path = require("path");
|
||||||
// const Vibrant = require("node-vibrant");
|
// const Vibrant = require("node-vibrant");
|
||||||
// const chroma = require("chroma-js");
|
// const chroma = require("chroma-js");
|
||||||
@@ -114,7 +118,8 @@ function transformMetaToNodeData(
|
|||||||
metaData: Record<string, unknown>,
|
metaData: Record<string, unknown>,
|
||||||
vibrantData: Palette,
|
vibrantData: Palette,
|
||||||
imagePath: string,
|
imagePath: string,
|
||||||
{ r, g, b }: { r: number; b: number; g: number }
|
{ r, g, b }: { r: number; b: number; g: number },
|
||||||
|
datePublished: string,
|
||||||
) {
|
) {
|
||||||
const vibrant = vibrantData ? processColors(vibrantData, imagePath) : null;
|
const vibrant = vibrantData ? processColors(vibrantData, imagePath) : null;
|
||||||
const vibrantHue = vibrantData.Vibrant!.getHsl()[0] * 360;
|
const vibrantHue = vibrantData.Vibrant!.getHsl()[0] * 360;
|
||||||
@@ -131,6 +136,7 @@ function transformMetaToNodeData(
|
|||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
dateTaken: metaData.DateTimeOriginal,
|
dateTaken: metaData.DateTimeOriginal,
|
||||||
|
datePublished,
|
||||||
meta: {
|
meta: {
|
||||||
Make: metaData.Make,
|
Make: metaData.Make,
|
||||||
Model: metaData.Model,
|
Model: metaData.Model,
|
||||||
@@ -139,6 +145,7 @@ function transformMetaToNodeData(
|
|||||||
ISO: metaData.ISO,
|
ISO: metaData.ISO,
|
||||||
DateTimeOriginal: metaData.DateTimeOriginal,
|
DateTimeOriginal: metaData.DateTimeOriginal,
|
||||||
CreateDate: metaData.CreateDate,
|
CreateDate: metaData.CreateDate,
|
||||||
|
ModifyDate: metaData.ModifyDate,
|
||||||
ShutterSpeedValue: metaData.ShutterSpeedValue,
|
ShutterSpeedValue: metaData.ShutterSpeedValue,
|
||||||
ApertureValue: metaData.ApertureValue,
|
ApertureValue: metaData.ApertureValue,
|
||||||
FocalLength: metaData.FocalLength,
|
FocalLength: metaData.FocalLength,
|
||||||
@@ -173,6 +180,11 @@ export const onCreateNode: GatsbyNode["onCreateNode"] = async function ({
|
|||||||
const { createNodeField } = actions;
|
const { createNodeField } = actions;
|
||||||
|
|
||||||
if (node.internal.type === "File" && node.sourceInstanceName === "gallery") {
|
if (node.internal.type === "File" && node.sourceInstanceName === "gallery") {
|
||||||
|
const { stdout: datePublished, stderr } = await exec(`git log --diff-filter=A --follow --format=%aI -1 -- ${node.absolutePath}`)
|
||||||
|
if (stderr.length) {
|
||||||
|
console.error('something went wrong checking publish date: ', stderr);
|
||||||
|
}
|
||||||
|
|
||||||
const metaData = await exifr.parse(node.absolutePath as string, {
|
const metaData = await exifr.parse(node.absolutePath as string, {
|
||||||
iptc: true,
|
iptc: true,
|
||||||
xmp: true,
|
xmp: true,
|
||||||
@@ -200,7 +212,8 @@ export const onCreateNode: GatsbyNode["onCreateNode"] = async function ({
|
|||||||
metaData,
|
metaData,
|
||||||
vibrantData,
|
vibrantData,
|
||||||
node.absolutePath as string,
|
node.absolutePath as string,
|
||||||
dominant
|
dominant,
|
||||||
|
datePublished
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+193
@@ -0,0 +1,193 @@
|
|||||||
|
a = {
|
||||||
|
ApplicationRecordVersion: '\x00\x04',
|
||||||
|
DateCreated: '2015-10-18T17:59:38',
|
||||||
|
TimeCreated: '175938',
|
||||||
|
DigitalCreationDate: '20151018',
|
||||||
|
DigitalCreationTime: '175938',
|
||||||
|
format: 'image/jpeg',
|
||||||
|
CreatorTool: 'Adobe Lightroom 5.4 (Macintosh)',
|
||||||
|
ModifyDate: '2022-07-09T21:16:39.000Z',
|
||||||
|
CreateDate: '2015-10-19T00:59:38.000Z',
|
||||||
|
MetadataDate: '2022-07-09T14:16:39-07:00',
|
||||||
|
Rating: 5,
|
||||||
|
LensInfo: [ 50, 50, 1.8, 1.8 ],
|
||||||
|
Lens: 'DT 50mm F1.8 SAM',
|
||||||
|
DocumentID: 'xmp.did:27795bf1-8bb2-49a0-807a-cf6150bd505b',
|
||||||
|
OriginalDocumentID: 'CE2B8F240393ADFDF9F092CF395C6632',
|
||||||
|
InstanceID: 'xmp.iid:27795bf1-8bb2-49a0-807a-cf6150bd505b',
|
||||||
|
History: [
|
||||||
|
{ action: 'derived', parameters: 'saved to new location' },
|
||||||
|
{
|
||||||
|
action: 'saved',
|
||||||
|
instanceID: 'xmp.iid:27795bf1-8bb2-49a0-807a-cf6150bd505b',
|
||||||
|
when: '2022-07-09T14:16:39-07:00',
|
||||||
|
softwareAgent: 'Adobe Lightroom 5.4 (Macintosh)',
|
||||||
|
changed: '/'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
DerivedFrom: {
|
||||||
|
documentID: 'CE2B8F240393ADFDF9F092CF395C6632',
|
||||||
|
originalDocumentID: 'CE2B8F240393ADFDF9F092CF395C6632'
|
||||||
|
},
|
||||||
|
good: true,
|
||||||
|
Version: 14.4,
|
||||||
|
ProcessVersion: 6.7,
|
||||||
|
WhiteBalance: 'Manual',
|
||||||
|
IncrementalTemperature: -11,
|
||||||
|
IncrementalTint: 23,
|
||||||
|
Exposure2012: 0,
|
||||||
|
Contrast2012: 6,
|
||||||
|
Highlights2012: 0,
|
||||||
|
Shadows2012: 0,
|
||||||
|
Whites2012: 35,
|
||||||
|
Blacks2012: -22,
|
||||||
|
Texture: 0,
|
||||||
|
Clarity2012: 0,
|
||||||
|
Dehaze: 0,
|
||||||
|
Vibrance: 0,
|
||||||
|
Saturation: 'Normal',
|
||||||
|
ParametricShadows: 0,
|
||||||
|
ParametricDarks: 0,
|
||||||
|
ParametricLights: 0,
|
||||||
|
ParametricHighlights: 0,
|
||||||
|
ParametricShadowSplit: 25,
|
||||||
|
ParametricMidtoneSplit: 50,
|
||||||
|
ParametricHighlightSplit: 75,
|
||||||
|
Sharpness: 'Normal',
|
||||||
|
LuminanceSmoothing: 0,
|
||||||
|
ColorNoiseReduction: 0,
|
||||||
|
HueAdjustmentRed: 0,
|
||||||
|
HueAdjustmentOrange: 0,
|
||||||
|
HueAdjustmentYellow: 0,
|
||||||
|
HueAdjustmentGreen: 0,
|
||||||
|
HueAdjustmentAqua: 0,
|
||||||
|
HueAdjustmentBlue: 0,
|
||||||
|
HueAdjustmentPurple: 0,
|
||||||
|
HueAdjustmentMagenta: 0,
|
||||||
|
SaturationAdjustmentRed: 0,
|
||||||
|
SaturationAdjustmentOrange: 0,
|
||||||
|
SaturationAdjustmentYellow: 0,
|
||||||
|
SaturationAdjustmentGreen: 0,
|
||||||
|
SaturationAdjustmentAqua: 0,
|
||||||
|
SaturationAdjustmentBlue: 0,
|
||||||
|
SaturationAdjustmentPurple: 0,
|
||||||
|
SaturationAdjustmentMagenta: 0,
|
||||||
|
LuminanceAdjustmentRed: 0,
|
||||||
|
LuminanceAdjustmentOrange: 0,
|
||||||
|
LuminanceAdjustmentYellow: 0,
|
||||||
|
LuminanceAdjustmentGreen: 0,
|
||||||
|
LuminanceAdjustmentAqua: 0,
|
||||||
|
LuminanceAdjustmentBlue: 0,
|
||||||
|
LuminanceAdjustmentPurple: 0,
|
||||||
|
LuminanceAdjustmentMagenta: 0,
|
||||||
|
SplitToningShadowHue: 0,
|
||||||
|
SplitToningShadowSaturation: 0,
|
||||||
|
SplitToningHighlightHue: 0,
|
||||||
|
SplitToningHighlightSaturation: 0,
|
||||||
|
SplitToningBalance: 0,
|
||||||
|
ColorGradeMidtoneHue: 0,
|
||||||
|
ColorGradeMidtoneSat: 0,
|
||||||
|
ColorGradeShadowLum: 0,
|
||||||
|
ColorGradeMidtoneLum: 0,
|
||||||
|
ColorGradeHighlightLum: 0,
|
||||||
|
ColorGradeBlending: 50,
|
||||||
|
ColorGradeGlobalHue: 0,
|
||||||
|
ColorGradeGlobalSat: 0,
|
||||||
|
ColorGradeGlobalLum: 0,
|
||||||
|
AutoLateralCA: 0,
|
||||||
|
LensProfileEnable: 0,
|
||||||
|
LensManualDistortionAmount: 0,
|
||||||
|
VignetteAmount: 0,
|
||||||
|
DefringePurpleAmount: 0,
|
||||||
|
DefringePurpleHueLo: 30,
|
||||||
|
DefringePurpleHueHi: 70,
|
||||||
|
DefringeGreenAmount: 0,
|
||||||
|
DefringeGreenHueLo: 40,
|
||||||
|
DefringeGreenHueHi: 60,
|
||||||
|
PerspectiveUpright: 0,
|
||||||
|
PerspectiveVertical: 0,
|
||||||
|
PerspectiveHorizontal: 0,
|
||||||
|
PerspectiveRotate: 0,
|
||||||
|
PerspectiveAspect: 0,
|
||||||
|
PerspectiveScale: 100,
|
||||||
|
PerspectiveX: 0,
|
||||||
|
PerspectiveY: 0,
|
||||||
|
GrainAmount: 0,
|
||||||
|
PostCropVignetteAmount: 0,
|
||||||
|
ShadowTint: 0,
|
||||||
|
RedHue: 0,
|
||||||
|
RedSaturation: 0,
|
||||||
|
GreenHue: 0,
|
||||||
|
GreenSaturation: 0,
|
||||||
|
BlueHue: 0,
|
||||||
|
BlueSaturation: 0,
|
||||||
|
ConvertToGrayscale: false,
|
||||||
|
OverrideLookVignette: false,
|
||||||
|
ToneCurveName2012: 'Linear',
|
||||||
|
CameraProfile: 'Embedded',
|
||||||
|
CameraProfileDigest: '54650A341B5B5CCAE8442D0B43A92BCE',
|
||||||
|
HasSettings: true,
|
||||||
|
CropTop: 0,
|
||||||
|
CropLeft: 0,
|
||||||
|
CropBottom: 1,
|
||||||
|
CropRight: 1,
|
||||||
|
CropAngle: 0,
|
||||||
|
CropConstrainToWarp: 0,
|
||||||
|
HasCrop: false,
|
||||||
|
AlreadyApplied: true,
|
||||||
|
ToneCurvePV2012: [ '0, 0', '255, 255' ],
|
||||||
|
ToneCurvePV2012Red: [ '0, 0', '255, 255' ],
|
||||||
|
ToneCurvePV2012Green: [ '0, 0', '255, 255' ],
|
||||||
|
ToneCurvePV2012Blue: [ '0, 0', '255, 255' ],
|
||||||
|
Make: 'SONY',
|
||||||
|
Model: 'SLT-A55V',
|
||||||
|
XResolution: 240,
|
||||||
|
YResolution: 240,
|
||||||
|
ResolutionUnit: 'inches',
|
||||||
|
Software: 'Adobe Lightroom 5.4 (Macintosh)',
|
||||||
|
ExposureTime: 0.01,
|
||||||
|
FNumber: 1.8,
|
||||||
|
ExposureProgram: 'Manual',
|
||||||
|
ISO: 200,
|
||||||
|
SensitivityType: 2,
|
||||||
|
RecommendedExposureIndex: 200,
|
||||||
|
ExifVersion: '2.3.1',
|
||||||
|
DateTimeOriginal: '2015-10-19T00:59:38.000Z',
|
||||||
|
OffsetTime: '-07:00',
|
||||||
|
ShutterSpeedValue: 6.643856,
|
||||||
|
ApertureValue: 1.695994,
|
||||||
|
BrightnessValue: 3,
|
||||||
|
ExposureCompensation: 0,
|
||||||
|
MaxApertureValue: 1.7,
|
||||||
|
MeteringMode: 'Pattern',
|
||||||
|
LightSource: 'Cloudy weather',
|
||||||
|
Flash: 'Flash did not fire, compulsory flash mode',
|
||||||
|
FocalLength: 50,
|
||||||
|
ColorSpace: 1,
|
||||||
|
FileSource: 'Digital Camera',
|
||||||
|
SceneType: 'Directly photographed',
|
||||||
|
CustomRendered: 'Normal',
|
||||||
|
ExposureMode: 'Manual',
|
||||||
|
FocalLengthIn35mmFormat: 75,
|
||||||
|
SceneCaptureType: 'Standard',
|
||||||
|
Contrast: 'Normal',
|
||||||
|
LensModel: 'DT 50mm F1.8 SAM',
|
||||||
|
GPSVersionID: '2.2.0.0',
|
||||||
|
GPSLatitudeRef: 'N',
|
||||||
|
GPSLatitude: [ 33, 25.7121, 0 ],
|
||||||
|
GPSLongitudeRef: 'W',
|
||||||
|
GPSLongitude: [ 111, 55.57122, 0 ],
|
||||||
|
GPSAltitude: 354.7,
|
||||||
|
GPSTimeStamp: '19:2:7',
|
||||||
|
GPSStatus: 'V',
|
||||||
|
GPSMeasureMode: '3',
|
||||||
|
GPSSpeedRef: 'K',
|
||||||
|
GPSSpeed: 33.8,
|
||||||
|
GPSTrackRef: 'T',
|
||||||
|
GPSTrack: 0.36,
|
||||||
|
GPSMapDatum: 'WGS-84',
|
||||||
|
GPSDateStamp: '2015:10:09',
|
||||||
|
GPSDifferential: 0,
|
||||||
|
latitude: 33.428535,
|
||||||
|
longitude: -111.926187
|
||||||
|
}
|
||||||
@@ -91,7 +91,7 @@ function Option({ item, state }: OptionProps) {
|
|||||||
return (
|
return (
|
||||||
<li
|
<li
|
||||||
{...optionProps}
|
{...optionProps}
|
||||||
className={`p-3 outline-none cursor-default flex items-center justify-between ${text} text-sm ${
|
className={`p-2 outline-none cursor-default flex items-center justify-between ${text} text-sm ${
|
||||||
isFocused ? "bg-transparentblack" : ""
|
isFocused ? "bg-transparentblack" : ""
|
||||||
} ${isSelected ? "font-bold" : ""}`}
|
} ${isSelected ? "font-bold" : ""}`}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ interface Row {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface MasonryGalleryProps {
|
interface MasonryGalleryProps {
|
||||||
images: GalleryImage[];
|
images: readonly GalleryImage[];
|
||||||
aspectsByBreakpoint: {
|
aspectsByBreakpoint: {
|
||||||
[breakpoint: string]: number;
|
[breakpoint: string]: number;
|
||||||
};
|
};
|
||||||
@@ -26,15 +26,17 @@ interface MasonryGalleryProps {
|
|||||||
debugRating?: boolean;
|
debugRating?: boolean;
|
||||||
linkState?: object;
|
linkState?: object;
|
||||||
showPalette?: boolean;
|
showPalette?: boolean;
|
||||||
|
singleRow?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MasonryGallery = ({
|
const MasonryGallery = ({
|
||||||
images,
|
images: _images,
|
||||||
aspectsByBreakpoint: aspectTargetsByBreakpoint,
|
aspectsByBreakpoint: aspectTargetsByBreakpoint,
|
||||||
debugHue,
|
debugHue,
|
||||||
debugRating,
|
debugRating,
|
||||||
linkState,
|
linkState,
|
||||||
showPalette,
|
showPalette,
|
||||||
|
singleRow,
|
||||||
}: MasonryGalleryProps) => {
|
}: MasonryGalleryProps) => {
|
||||||
const [isClient, setIsClient] = React.useState(false);
|
const [isClient, setIsClient] = React.useState(false);
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
@@ -57,8 +59,8 @@ const MasonryGallery = ({
|
|||||||
}px)`;
|
}px)`;
|
||||||
|
|
||||||
const aspectRatios = React.useMemo(
|
const aspectRatios = React.useMemo(
|
||||||
() => R.map(getAspectRatio, images).filter(Boolean),
|
() => R.map(getAspectRatio, _images).filter(Boolean),
|
||||||
[images]
|
[_images]
|
||||||
) as number[];
|
) as number[];
|
||||||
|
|
||||||
const targetAspect = aspectTargetsByBreakpoint[breakpoint];
|
const targetAspect = aspectTargetsByBreakpoint[breakpoint];
|
||||||
@@ -83,6 +85,11 @@ const MasonryGallery = ({
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
// no-op instead of starting a new row
|
||||||
|
if (singleRow) {
|
||||||
|
return [currentRow];
|
||||||
|
}
|
||||||
|
// start a new row
|
||||||
return [
|
return [
|
||||||
...acc,
|
...acc,
|
||||||
currentRow,
|
currentRow,
|
||||||
@@ -97,14 +104,16 @@ const MasonryGallery = ({
|
|||||||
),
|
),
|
||||||
R.indexBy(R.prop("startIndex"))
|
R.indexBy(R.prop("startIndex"))
|
||||||
)(aspectRatios),
|
)(aspectRatios),
|
||||||
[aspectRatios, targetAspect]
|
[aspectRatios, targetAspect, singleRow]
|
||||||
);
|
);
|
||||||
|
|
||||||
const sortedImageList = React.useMemo(
|
const sortedImageList = React.useMemo(
|
||||||
() => images.map((image) => image.base),
|
() => _images.map((image) => image.base),
|
||||||
[images]
|
[_images]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const images = singleRow ? _images.slice(0, rows[0].images) : _images;
|
||||||
|
|
||||||
let cursor = 0;
|
let cursor = 0;
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ export function Select<T extends object>(props: AriaSelectProps<T>) {
|
|||||||
<button
|
<button
|
||||||
{...mergeProps(buttonProps, focusProps)}
|
{...mergeProps(buttonProps, focusProps)}
|
||||||
className={`py-[5px] px-3 w-[150px] flex flex-row items-center justify-between overflow-hidden cursor-default rounded border hover:bg-transparentblack ${
|
className={`py-[5px] px-3 w-[150px] flex flex-row items-center justify-between overflow-hidden cursor-default rounded border hover:bg-transparentblack ${
|
||||||
isFocusVisible ? "border-green-500" : "border-black"
|
isFocusVisible ? "border-green-700" : "border-black"
|
||||||
} ${state.isOpen ? "bg-gray-100" : "bg-white"}`}
|
} ${state.isOpen ? "bg-gray-100" : "bg-white"}`}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
>
|
>
|
||||||
|
|||||||
Vendored
+19
-1
@@ -571,6 +571,7 @@ type FileFieldsFilterInput = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type FileFieldsImageMeta = {
|
type FileFieldsImageMeta = {
|
||||||
|
readonly datePublished: Maybe<Scalars['String']>;
|
||||||
readonly dateTaken: Maybe<Scalars['Date']>;
|
readonly dateTaken: Maybe<Scalars['Date']>;
|
||||||
readonly dominantHue: Maybe<ReadonlyArray<Maybe<Scalars['Float']>>>;
|
readonly dominantHue: Maybe<ReadonlyArray<Maybe<Scalars['Float']>>>;
|
||||||
readonly meta: Maybe<FileFieldsImageMetaMeta>;
|
readonly meta: Maybe<FileFieldsImageMetaMeta>;
|
||||||
@@ -587,6 +588,7 @@ type FileFieldsImageMeta_dateTakenArgs = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type FileFieldsImageMetaFieldSelector = {
|
type FileFieldsImageMetaFieldSelector = {
|
||||||
|
readonly datePublished: InputMaybe<FieldSelectorEnum>;
|
||||||
readonly dateTaken: InputMaybe<FieldSelectorEnum>;
|
readonly dateTaken: InputMaybe<FieldSelectorEnum>;
|
||||||
readonly dominantHue: InputMaybe<FieldSelectorEnum>;
|
readonly dominantHue: InputMaybe<FieldSelectorEnum>;
|
||||||
readonly meta: InputMaybe<FileFieldsImageMetaMetaFieldSelector>;
|
readonly meta: InputMaybe<FileFieldsImageMetaMetaFieldSelector>;
|
||||||
@@ -595,6 +597,7 @@ type FileFieldsImageMetaFieldSelector = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type FileFieldsImageMetaFilterInput = {
|
type FileFieldsImageMetaFilterInput = {
|
||||||
|
readonly datePublished: InputMaybe<StringQueryOperatorInput>;
|
||||||
readonly dateTaken: InputMaybe<DateQueryOperatorInput>;
|
readonly dateTaken: InputMaybe<DateQueryOperatorInput>;
|
||||||
readonly dominantHue: InputMaybe<FloatQueryOperatorInput>;
|
readonly dominantHue: InputMaybe<FloatQueryOperatorInput>;
|
||||||
readonly meta: InputMaybe<FileFieldsImageMetaMetaFilterInput>;
|
readonly meta: InputMaybe<FileFieldsImageMetaMetaFilterInput>;
|
||||||
@@ -617,6 +620,7 @@ type FileFieldsImageMetaMeta = {
|
|||||||
readonly Location: Maybe<Scalars['String']>;
|
readonly Location: Maybe<Scalars['String']>;
|
||||||
readonly Make: Maybe<Scalars['String']>;
|
readonly Make: Maybe<Scalars['String']>;
|
||||||
readonly Model: Maybe<Scalars['String']>;
|
readonly Model: Maybe<Scalars['String']>;
|
||||||
|
readonly ModifyDate: Maybe<Scalars['Date']>;
|
||||||
readonly ObjectName: Maybe<Scalars['String']>;
|
readonly ObjectName: Maybe<Scalars['String']>;
|
||||||
readonly Rating: Maybe<Scalars['Int']>;
|
readonly Rating: Maybe<Scalars['Int']>;
|
||||||
readonly ShutterSpeedValue: Maybe<Scalars['Float']>;
|
readonly ShutterSpeedValue: Maybe<Scalars['Float']>;
|
||||||
@@ -639,6 +643,14 @@ type FileFieldsImageMetaMeta_DateTimeOriginalArgs = {
|
|||||||
locale: InputMaybe<Scalars['String']>;
|
locale: InputMaybe<Scalars['String']>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
type FileFieldsImageMetaMeta_ModifyDateArgs = {
|
||||||
|
difference: InputMaybe<Scalars['String']>;
|
||||||
|
formatString: InputMaybe<Scalars['String']>;
|
||||||
|
fromNow: InputMaybe<Scalars['Boolean']>;
|
||||||
|
locale: InputMaybe<Scalars['String']>;
|
||||||
|
};
|
||||||
|
|
||||||
type FileFieldsImageMetaMetaFieldSelector = {
|
type FileFieldsImageMetaMetaFieldSelector = {
|
||||||
readonly ApertureValue: InputMaybe<FieldSelectorEnum>;
|
readonly ApertureValue: InputMaybe<FieldSelectorEnum>;
|
||||||
readonly Caption: InputMaybe<FieldSelectorEnum>;
|
readonly Caption: InputMaybe<FieldSelectorEnum>;
|
||||||
@@ -654,6 +666,7 @@ type FileFieldsImageMetaMetaFieldSelector = {
|
|||||||
readonly Location: InputMaybe<FieldSelectorEnum>;
|
readonly Location: InputMaybe<FieldSelectorEnum>;
|
||||||
readonly Make: InputMaybe<FieldSelectorEnum>;
|
readonly Make: InputMaybe<FieldSelectorEnum>;
|
||||||
readonly Model: InputMaybe<FieldSelectorEnum>;
|
readonly Model: InputMaybe<FieldSelectorEnum>;
|
||||||
|
readonly ModifyDate: InputMaybe<FieldSelectorEnum>;
|
||||||
readonly ObjectName: InputMaybe<FieldSelectorEnum>;
|
readonly ObjectName: InputMaybe<FieldSelectorEnum>;
|
||||||
readonly Rating: InputMaybe<FieldSelectorEnum>;
|
readonly Rating: InputMaybe<FieldSelectorEnum>;
|
||||||
readonly ShutterSpeedValue: InputMaybe<FieldSelectorEnum>;
|
readonly ShutterSpeedValue: InputMaybe<FieldSelectorEnum>;
|
||||||
@@ -675,6 +688,7 @@ type FileFieldsImageMetaMetaFilterInput = {
|
|||||||
readonly Location: InputMaybe<StringQueryOperatorInput>;
|
readonly Location: InputMaybe<StringQueryOperatorInput>;
|
||||||
readonly Make: InputMaybe<StringQueryOperatorInput>;
|
readonly Make: InputMaybe<StringQueryOperatorInput>;
|
||||||
readonly Model: InputMaybe<StringQueryOperatorInput>;
|
readonly Model: InputMaybe<StringQueryOperatorInput>;
|
||||||
|
readonly ModifyDate: InputMaybe<DateQueryOperatorInput>;
|
||||||
readonly ObjectName: InputMaybe<StringQueryOperatorInput>;
|
readonly ObjectName: InputMaybe<StringQueryOperatorInput>;
|
||||||
readonly Rating: InputMaybe<IntQueryOperatorInput>;
|
readonly Rating: InputMaybe<IntQueryOperatorInput>;
|
||||||
readonly ShutterSpeedValue: InputMaybe<FloatQueryOperatorInput>;
|
readonly ShutterSpeedValue: InputMaybe<FloatQueryOperatorInput>;
|
||||||
@@ -696,6 +710,7 @@ type FileFieldsImageMetaMetaSortInput = {
|
|||||||
readonly Location: InputMaybe<SortOrderEnum>;
|
readonly Location: InputMaybe<SortOrderEnum>;
|
||||||
readonly Make: InputMaybe<SortOrderEnum>;
|
readonly Make: InputMaybe<SortOrderEnum>;
|
||||||
readonly Model: InputMaybe<SortOrderEnum>;
|
readonly Model: InputMaybe<SortOrderEnum>;
|
||||||
|
readonly ModifyDate: InputMaybe<SortOrderEnum>;
|
||||||
readonly ObjectName: InputMaybe<SortOrderEnum>;
|
readonly ObjectName: InputMaybe<SortOrderEnum>;
|
||||||
readonly Rating: InputMaybe<SortOrderEnum>;
|
readonly Rating: InputMaybe<SortOrderEnum>;
|
||||||
readonly ShutterSpeedValue: InputMaybe<SortOrderEnum>;
|
readonly ShutterSpeedValue: InputMaybe<SortOrderEnum>;
|
||||||
@@ -703,6 +718,7 @@ type FileFieldsImageMetaMetaSortInput = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type FileFieldsImageMetaSortInput = {
|
type FileFieldsImageMetaSortInput = {
|
||||||
|
readonly datePublished: InputMaybe<SortOrderEnum>;
|
||||||
readonly dateTaken: InputMaybe<SortOrderEnum>;
|
readonly dateTaken: InputMaybe<SortOrderEnum>;
|
||||||
readonly dominantHue: InputMaybe<SortOrderEnum>;
|
readonly dominantHue: InputMaybe<SortOrderEnum>;
|
||||||
readonly meta: InputMaybe<FileFieldsImageMetaMetaSortInput>;
|
readonly meta: InputMaybe<FileFieldsImageMetaMetaSortInput>;
|
||||||
@@ -2547,10 +2563,12 @@ type GalleryImageQueryVariables = Exact<{
|
|||||||
|
|
||||||
type GalleryImageQuery = { readonly file: { readonly base: string, readonly publicURL: string | null, readonly childImageSharp: { readonly gatsbyImageData: import('gatsby-plugin-image').IGatsbyImageData, readonly fluid: { readonly aspectRatio: number } | null } | null, readonly fields: { readonly imageMeta: { readonly dateTaken: string | null, readonly meta: { readonly Make: string | null, readonly Model: string | null, readonly ExposureTime: number | null, readonly FNumber: number | null, readonly ISO: number | null, readonly DateTimeOriginal: string | null, readonly CreateDate: string | null, readonly ShutterSpeedValue: number | null, readonly ApertureValue: number | null, readonly FocalLength: number | null, readonly LensModel: string | null, readonly ObjectName: string | null, readonly Caption: string | null, readonly Location: string | null, readonly City: string | null, readonly State: string | null } | null, readonly vibrant: { readonly DarkMuted: ReadonlyArray<number | null> | null, readonly DarkVibrant: ReadonlyArray<number | null> | null, readonly LightMuted: ReadonlyArray<number | null> | null, readonly LightVibrant: ReadonlyArray<number | null> | null, readonly Vibrant: ReadonlyArray<number | null> | null, readonly Muted: ReadonlyArray<number | null> | null } | null } | null } | null } | null };
|
type GalleryImageQuery = { readonly file: { readonly base: string, readonly publicURL: string | null, readonly childImageSharp: { readonly gatsbyImageData: import('gatsby-plugin-image').IGatsbyImageData, readonly fluid: { readonly aspectRatio: number } | null } | null, readonly fields: { readonly imageMeta: { readonly dateTaken: string | null, readonly meta: { readonly Make: string | null, readonly Model: string | null, readonly ExposureTime: number | null, readonly FNumber: number | null, readonly ISO: number | null, readonly DateTimeOriginal: string | null, readonly CreateDate: string | null, readonly ShutterSpeedValue: number | null, readonly ApertureValue: number | null, readonly FocalLength: number | null, readonly LensModel: string | null, readonly ObjectName: string | null, readonly Caption: string | null, readonly Location: string | null, readonly City: string | null, readonly State: string | null } | null, readonly vibrant: { readonly DarkMuted: ReadonlyArray<number | null> | null, readonly DarkVibrant: ReadonlyArray<number | null> | null, readonly LightMuted: ReadonlyArray<number | null> | null, readonly LightVibrant: ReadonlyArray<number | null> | null, readonly Vibrant: ReadonlyArray<number | null> | null, readonly Muted: ReadonlyArray<number | null> | null } | null } | null } | null } | null };
|
||||||
|
|
||||||
|
type GalleryImageFileFragment = { readonly nodes: ReadonlyArray<{ readonly base: string, readonly childImageSharp: { readonly gatsbyImageData: import('gatsby-plugin-image').IGatsbyImageData, readonly fluid: { readonly aspectRatio: number } | null } | null, readonly fields: { readonly imageMeta: { readonly vibrantHue: number | null, readonly dominantHue: ReadonlyArray<number | null> | null, readonly dateTaken: string | null, readonly datePublished: string | null, readonly meta: { readonly Keywords: ReadonlyArray<string | null> | null, readonly Rating: number | null, readonly ObjectName: string | null, readonly CreateDate: string | null, readonly ModifyDate: string | null } | null, readonly vibrant: { readonly DarkMuted: ReadonlyArray<number | null> | null, readonly DarkVibrant: ReadonlyArray<number | null> | null, readonly LightMuted: ReadonlyArray<number | null> | null, readonly LightVibrant: ReadonlyArray<number | null> | null, readonly Vibrant: ReadonlyArray<number | null> | null, readonly Muted: ReadonlyArray<number | null> | null } | null } | null } | null }> };
|
||||||
|
|
||||||
type GalleryPageQueryQueryVariables = Exact<{ [key: string]: never; }>;
|
type GalleryPageQueryQueryVariables = Exact<{ [key: string]: never; }>;
|
||||||
|
|
||||||
|
|
||||||
type GalleryPageQueryQuery = { readonly allFile: { readonly nodes: ReadonlyArray<{ readonly relativePath: string, readonly base: string, readonly childImageSharp: { readonly gatsbyImageData: import('gatsby-plugin-image').IGatsbyImageData, readonly fluid: { readonly aspectRatio: number } | null } | null, readonly fields: { readonly imageMeta: { readonly vibrantHue: number | null, readonly dominantHue: ReadonlyArray<number | null> | null, readonly dateTaken: string | null, readonly meta: { readonly Keywords: ReadonlyArray<string | null> | null, readonly Rating: number | null, readonly ObjectName: string | null } | null, readonly vibrant: { readonly DarkMuted: ReadonlyArray<number | null> | null, readonly DarkVibrant: ReadonlyArray<number | null> | null, readonly LightMuted: ReadonlyArray<number | null> | null, readonly LightVibrant: ReadonlyArray<number | null> | null, readonly Vibrant: ReadonlyArray<number | null> | null, readonly Muted: ReadonlyArray<number | null> | null } | null } | null } | null }> } };
|
type GalleryPageQueryQuery = { readonly recents: { readonly nodes: ReadonlyArray<{ readonly base: string, readonly childImageSharp: { readonly gatsbyImageData: import('gatsby-plugin-image').IGatsbyImageData, readonly fluid: { readonly aspectRatio: number } | null } | null, readonly fields: { readonly imageMeta: { readonly vibrantHue: number | null, readonly dominantHue: ReadonlyArray<number | null> | null, readonly dateTaken: string | null, readonly datePublished: string | null, readonly meta: { readonly Keywords: ReadonlyArray<string | null> | null, readonly Rating: number | null, readonly ObjectName: string | null, readonly CreateDate: string | null, readonly ModifyDate: string | null } | null, readonly vibrant: { readonly DarkMuted: ReadonlyArray<number | null> | null, readonly DarkVibrant: ReadonlyArray<number | null> | null, readonly LightMuted: ReadonlyArray<number | null> | null, readonly LightVibrant: ReadonlyArray<number | null> | null, readonly Vibrant: ReadonlyArray<number | null> | null, readonly Muted: ReadonlyArray<number | null> | null } | null } | null } | null }> }, readonly all: { readonly nodes: ReadonlyArray<{ readonly base: string, readonly childImageSharp: { readonly gatsbyImageData: import('gatsby-plugin-image').IGatsbyImageData, readonly fluid: { readonly aspectRatio: number } | null } | null, readonly fields: { readonly imageMeta: { readonly vibrantHue: number | null, readonly dominantHue: ReadonlyArray<number | null> | null, readonly dateTaken: string | null, readonly datePublished: string | null, readonly meta: { readonly Keywords: ReadonlyArray<string | null> | null, readonly Rating: number | null, readonly ObjectName: string | null, readonly CreateDate: string | null, readonly ModifyDate: string | null } | null, readonly vibrant: { readonly DarkMuted: ReadonlyArray<number | null> | null, readonly DarkVibrant: ReadonlyArray<number | null> | null, readonly LightMuted: ReadonlyArray<number | null> | null, readonly LightVibrant: ReadonlyArray<number | null> | null, readonly Vibrant: ReadonlyArray<number | null> | null, readonly Muted: ReadonlyArray<number | null> | null } | null } | null } | null }> } };
|
||||||
|
|
||||||
type GatsbyImageSharpFixedFragment = { readonly base64: string | null, readonly width: number, readonly height: number, readonly src: string, readonly srcSet: string };
|
type GatsbyImageSharpFixedFragment = { readonly base64: string | null, readonly width: number, readonly height: number, readonly src: string, readonly srcSet: string };
|
||||||
|
|
||||||
|
|||||||
+65
-19
@@ -7,6 +7,7 @@ import { Helmet } from "react-helmet";
|
|||||||
import MasonryGallery from "../components/MasonryGallery";
|
import MasonryGallery from "../components/MasonryGallery";
|
||||||
import KeywordsPicker from "../components/KeywordsPicker";
|
import KeywordsPicker from "../components/KeywordsPicker";
|
||||||
import {
|
import {
|
||||||
|
compareDates,
|
||||||
getGalleryPageUrl,
|
getGalleryPageUrl,
|
||||||
getHelmetSafeBodyStyle,
|
getHelmetSafeBodyStyle,
|
||||||
getVibrantStyle,
|
getVibrantStyle,
|
||||||
@@ -19,12 +20,24 @@ import ColorPalette from "@spectrum-icons/workflow/ColorPalette";
|
|||||||
const SORT_KEYS = {
|
const SORT_KEYS = {
|
||||||
hue: ["fields", "imageMeta", "vibrantHue"],
|
hue: ["fields", "imageMeta", "vibrantHue"],
|
||||||
rating: ["fields", "imageMeta", "meta", "Rating"],
|
rating: ["fields", "imageMeta", "meta", "Rating"],
|
||||||
hue_debug: ["fields", "imageMeta", "dominantHue", 0],
|
// hue_debug: ["fields", "imageMeta", "dominantHue", 0],
|
||||||
date: [],
|
hue_debug: ["fields", "imageMeta", "dominantHue", "0"],
|
||||||
|
date: ["fields", "imageMeta", "dateTaken"],
|
||||||
|
modified: ["fields", "imageMeta", "datePublished"],
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export type GalleryImage =
|
export type GalleryImage =
|
||||||
Queries.GalleryPageQueryQuery["allFile"]["nodes"][number];
|
Queries.GalleryPageQueryQuery["all"]["nodes"][number];
|
||||||
|
|
||||||
|
function smartCompareDates(key: keyof typeof SORT_KEYS, left: GalleryImage, right: GalleryImage) {
|
||||||
|
let diff = compareDates(SORT_KEYS[key], left, right);
|
||||||
|
console.log("🚀 ~ file: photogallery.tsx:34 ~ smartCompareDates ~ diff:", diff)
|
||||||
|
if (diff !== 0) {
|
||||||
|
return diff;
|
||||||
|
}
|
||||||
|
console.log('falling back to date')
|
||||||
|
return compareDates(SORT_KEYS.date, left, right);
|
||||||
|
}
|
||||||
|
|
||||||
const GalleryPage = ({ data }: PageProps<Queries.GalleryPageQueryQuery>) => {
|
const GalleryPage = ({ data }: PageProps<Queries.GalleryPageQueryQuery>) => {
|
||||||
const hash =
|
const hash =
|
||||||
@@ -128,16 +141,8 @@ const GalleryPage = ({ data }: PageProps<Queries.GalleryPageQueryQuery>) => {
|
|||||||
|
|
||||||
const images: GalleryImage[] = React.useMemo(() => {
|
const images: GalleryImage[] = React.useMemo(() => {
|
||||||
const sort =
|
const sort =
|
||||||
sortKey === "date"
|
sortKey === "date" || sortKey === "modified"
|
||||||
? R.sort((node1: typeof data["allFile"]["nodes"][number], node2) => {
|
? R.sort((node1: typeof data["all"]["nodes"][number], node2) => smartCompareDates(sortKey, node1, node2))
|
||||||
const date1 = new Date(
|
|
||||||
R.pathOr("", ["fields", "imageMeta", "dateTaken"], node1)
|
|
||||||
);
|
|
||||||
const date2 = new Date(
|
|
||||||
R.pathOr("", ["fields", "imageMeta", "dateTaken"], node2)
|
|
||||||
);
|
|
||||||
return -1 * (date1.getTime() - date2.getTime());
|
|
||||||
})
|
|
||||||
: R.sort(
|
: R.sort(
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
R.descend(R.path<GalleryImage>(SORT_KEYS[sortKey]))
|
R.descend(R.path<GalleryImage>(SORT_KEYS[sortKey]))
|
||||||
@@ -157,7 +162,7 @@ const GalleryPage = ({ data }: PageProps<Queries.GalleryPageQueryQuery>) => {
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
sort,
|
sort,
|
||||||
filter
|
filter
|
||||||
)(data.allFile.nodes) as any;
|
)(data.all.nodes) as any;
|
||||||
return ret;
|
return ret;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("caught images!", e);
|
console.log("caught images!", e);
|
||||||
@@ -165,6 +170,10 @@ const GalleryPage = ({ data }: PageProps<Queries.GalleryPageQueryQuery>) => {
|
|||||||
}
|
}
|
||||||
}, [data, sortKey, filterKeyword]);
|
}, [data, sortKey, filterKeyword]);
|
||||||
|
|
||||||
|
const recents = React.useMemo(() => {
|
||||||
|
return R.sort((left, right) => smartCompareDates('modified', left, right), data.recents.nodes)
|
||||||
|
}, [data, 'hi'])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* @ts-ignore */}
|
{/* @ts-ignore */}
|
||||||
@@ -174,6 +183,7 @@ const GalleryPage = ({ data }: PageProps<Queries.GalleryPageQueryQuery>) => {
|
|||||||
className="bg-white transition-color"
|
className="bg-white transition-color"
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
style={getHelmetSafeBodyStyle(
|
style={getHelmetSafeBodyStyle(
|
||||||
|
// @ts-ignore shrug
|
||||||
getVibrantStyle({
|
getVibrantStyle({
|
||||||
Muted: [0, 0, 0],
|
Muted: [0, 0, 0],
|
||||||
LightMuted: [0, 0, 0],
|
LightMuted: [0, 0, 0],
|
||||||
@@ -195,6 +205,29 @@ const GalleryPage = ({ data }: PageProps<Queries.GalleryPageQueryQuery>) => {
|
|||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="px-4 md:px-8">
|
||||||
|
<h3 id="recently" className="mx-2 font-bold">
|
||||||
|
Recently published
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<MasonryGallery
|
||||||
|
aspectsByBreakpoint={{
|
||||||
|
xs: 2,
|
||||||
|
sm: 2,
|
||||||
|
md: 3,
|
||||||
|
lg: 4,
|
||||||
|
xl: 5,
|
||||||
|
"2xl": 6.1,
|
||||||
|
"3xl": 8,
|
||||||
|
}}
|
||||||
|
images={recents}
|
||||||
|
singleRow
|
||||||
|
/>
|
||||||
|
<div className="px-4 md:px-8 mt-4 pt-2 border-t">
|
||||||
|
<h3 id="all" className="mx-2 font-bold">
|
||||||
|
All images
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
<div className="flex flex-col lg:flex-row lg:items-end justify-between px-4 md:px-8 sm:mx-auto">
|
<div className="flex flex-col lg:flex-row lg:items-end justify-between px-4 md:px-8 sm:mx-auto">
|
||||||
<KeywordsPicker
|
<KeywordsPicker
|
||||||
keywords={[
|
keywords={[
|
||||||
@@ -237,7 +270,8 @@ const GalleryPage = ({ data }: PageProps<Queries.GalleryPageQueryQuery>) => {
|
|||||||
selectedKey={sortKey}
|
selectedKey={sortKey}
|
||||||
>
|
>
|
||||||
<Item key="rating">Curated</Item>
|
<Item key="rating">Curated</Item>
|
||||||
<Item key="date">Date</Item>
|
<Item key="modified">Date published</Item>
|
||||||
|
<Item key="date">Date taken</Item>
|
||||||
<Item key="hue">Hue</Item>
|
<Item key="hue">Hue</Item>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
@@ -268,12 +302,23 @@ const GalleryPage = ({ data }: PageProps<Queries.GalleryPageQueryQuery>) => {
|
|||||||
|
|
||||||
export const query = graphql`
|
export const query = graphql`
|
||||||
query GalleryPageQuery {
|
query GalleryPageQuery {
|
||||||
allFile(
|
recents: allFile(
|
||||||
|
filter: { sourceInstanceName: { eq: "gallery" } }
|
||||||
|
sort: { fields: { imageMeta: { datePublished: DESC } } }
|
||||||
|
limit: 7
|
||||||
|
) {
|
||||||
|
...GalleryImageFile
|
||||||
|
}
|
||||||
|
all: allFile(
|
||||||
filter: { sourceInstanceName: { eq: "gallery" } }
|
filter: { sourceInstanceName: { eq: "gallery" } }
|
||||||
sort: { fields: { imageMeta: { dateTaken: DESC } } }
|
sort: { fields: { imageMeta: { dateTaken: DESC } } }
|
||||||
) {
|
) {
|
||||||
|
...GalleryImageFile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment GalleryImageFile on FileConnection {
|
||||||
nodes {
|
nodes {
|
||||||
relativePath
|
|
||||||
base
|
base
|
||||||
childImageSharp {
|
childImageSharp {
|
||||||
fluid {
|
fluid {
|
||||||
@@ -290,20 +335,21 @@ export const query = graphql`
|
|||||||
vibrantHue
|
vibrantHue
|
||||||
dominantHue
|
dominantHue
|
||||||
dateTaken
|
dateTaken
|
||||||
|
datePublished
|
||||||
meta {
|
meta {
|
||||||
Keywords
|
Keywords
|
||||||
Rating
|
Rating
|
||||||
ObjectName
|
ObjectName
|
||||||
|
CreateDate
|
||||||
|
ModifyDate
|
||||||
}
|
}
|
||||||
vibrant {
|
vibrant {
|
||||||
# Vibrant
|
|
||||||
...VibrantColors
|
...VibrantColors
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default GalleryPage;
|
export default GalleryPage;
|
||||||
|
|||||||
+37
-9
@@ -1,18 +1,23 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import { pathOr } from "ramda";
|
||||||
// import kebabCase from 'lodash/kebabCase';
|
// import kebabCase from 'lodash/kebabCase';
|
||||||
|
|
||||||
import React from "react";
|
|
||||||
import { HomepageImage } from "./pages";
|
import { HomepageImage } from "./pages";
|
||||||
import { GalleryImage } from "./pages/photogallery";
|
import { GalleryImage } from "./pages/photogallery";
|
||||||
|
|
||||||
export const getMeta = <T extends GalleryImage | HomepageImage>(image: T) => image.fields?.imageMeta;
|
export const getMeta = <T extends GalleryImage | HomepageImage>(image: T) =>
|
||||||
|
image.fields?.imageMeta;
|
||||||
|
|
||||||
export const getName = (image: GalleryImage) =>
|
export const getName = (image: GalleryImage) =>
|
||||||
image.fields?.imageMeta?.meta?.ObjectName || image.base;
|
image.fields?.imageMeta?.meta?.ObjectName || image.base;
|
||||||
|
|
||||||
// some pleasing default colors for SSR and initial hydration
|
// some pleasing default colors for SSR and initial hydration
|
||||||
export const getVibrant = (image: GalleryImage | HomepageImage) => getMeta(image)?.vibrant;
|
export const getVibrant = (image: GalleryImage | HomepageImage) =>
|
||||||
|
getMeta(image)?.vibrant;
|
||||||
|
|
||||||
export const hasName = (image: GalleryImage) => Boolean(image.fields?.imageMeta?.meta?.ObjectName);
|
export const hasName = (image: GalleryImage) =>
|
||||||
|
Boolean(image.fields?.imageMeta?.meta?.ObjectName);
|
||||||
|
|
||||||
export const getAspectRatio = (image: GalleryImage | HomepageImage): number =>
|
export const getAspectRatio = (image: GalleryImage | HomepageImage): number =>
|
||||||
image.childImageSharp?.fluid?.aspectRatio ?? 1;
|
image.childImageSharp?.fluid?.aspectRatio ?? 1;
|
||||||
@@ -25,7 +30,10 @@ export const getCanonicalSize = (image: GalleryImage) => ({
|
|||||||
export const getRgba = (palette: string[], alpha: number) =>
|
export const getRgba = (palette: string[], alpha: number) =>
|
||||||
`rgba(${palette[0]}, ${palette[1]}, ${palette[2]}, ${alpha || 1})`;
|
`rgba(${palette[0]}, ${palette[1]}, ${palette[2]}, ${alpha || 1})`;
|
||||||
|
|
||||||
export const getVibrantStyle = (vibrant: Queries.FileFieldsImageMetaVibrant, screenHeight?: number) => ({
|
export const getVibrantStyle = (
|
||||||
|
vibrant: Queries.FileFieldsImageMetaVibrant,
|
||||||
|
screenHeight?: number
|
||||||
|
) => ({
|
||||||
"--muted": vibrant.Muted,
|
"--muted": vibrant.Muted,
|
||||||
"--dark-muted": vibrant.DarkMuted,
|
"--dark-muted": vibrant.DarkMuted,
|
||||||
"--light-muted": vibrant.LightMuted,
|
"--light-muted": vibrant.LightMuted,
|
||||||
@@ -40,10 +48,12 @@ export const getHelmetSafeBodyStyle = (style: React.CSSProperties) => {
|
|||||||
if (typeof window === "undefined") {
|
if (typeof window === "undefined") {
|
||||||
return style;
|
return style;
|
||||||
}
|
}
|
||||||
return Object.keys(style)
|
return (
|
||||||
|
Object.keys(style)
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
.map((key) => `${key}: ${style[key]};`)
|
.map((key) => `${key}: ${style[key]};`)
|
||||||
.join("");
|
.join("")
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const gcd = (a: number, b: number): number => {
|
const gcd = (a: number, b: number): number => {
|
||||||
@@ -55,6 +65,9 @@ const gcd = (a: number, b: number): number => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const getShutterFractionFromExposureTime = (exposureTime: number) => {
|
export const getShutterFractionFromExposureTime = (exposureTime: number) => {
|
||||||
|
if (exposureTime === 0.3333333333333333) {
|
||||||
|
return "1/3";
|
||||||
|
}
|
||||||
if (exposureTime === 0.03333333333333333) {
|
if (exposureTime === 0.03333333333333333) {
|
||||||
return "1/30";
|
return "1/30";
|
||||||
}
|
}
|
||||||
@@ -91,7 +104,10 @@ interface galleryPageUrlProps {
|
|||||||
sortKey: string;
|
sortKey: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getGalleryPageUrl = ({ keyword, sortKey }: galleryPageUrlProps, hash: string) => {
|
export const getGalleryPageUrl = (
|
||||||
|
{ keyword, sortKey }: galleryPageUrlProps,
|
||||||
|
hash: string
|
||||||
|
) => {
|
||||||
const url = new URL(
|
const url = new URL(
|
||||||
`${
|
`${
|
||||||
typeof window !== "undefined"
|
typeof window !== "undefined"
|
||||||
@@ -118,3 +134,15 @@ export const getGalleryPageUrl = ({ keyword, sortKey }: galleryPageUrlProps, has
|
|||||||
}
|
}
|
||||||
return url.href.toString().replace(url.origin, "");
|
return url.href.toString().replace(url.origin, "");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function compareDates<T>(
|
||||||
|
date_path: readonly string[],
|
||||||
|
left: T,
|
||||||
|
right: T
|
||||||
|
): number {
|
||||||
|
// why tf do my dates have newlines in them?!?!
|
||||||
|
const date1 = new Date(pathOr("", date_path, left).replace(/\s/g, ''));
|
||||||
|
const date2 = new Date(pathOr("", date_path, right).replace(/\s/g, ''));
|
||||||
|
const diff = -1 * (date1.getTime() - date2.getTime());
|
||||||
|
return diff;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user